perl coro socket编程(1)

本文通过改造传统Perl Socket编程示例,展示了如何利用coro模块实现非阻塞I/O,提高并发处理能力。文中包括客户端多进程并发发送数据及服务器端采用select复用模式接收数据的具体实现。

coro提供了perl的非阻塞io.但是作者提供的文档太简略了,例子也没有.

自己尝试写了几个例子.

分别实现CU上仙子提供的例子以及AE自带的echo server例子

相关的模块有

coro:;socket,coro::handle

ae::socket,ae::handle

 

先看看传统的socket编程(CU上仙子提供的例子)

客户端使用多进程并发

use strict;
use IO::Socket;

my @childs;
   
for (1..3) {  # fork 3个子进程,同时发送数据

   my $child = fork;
   if ($child) {
      push(@childs, $child);

   } else {
     # 创建到server的连接socket
      my $sock=IO::Socket::INET->new(PeerAddr => 'localhost',
                               PeerPort => 1234,
                               Proto    => 'tcp') or die $@;

      for (1..10) {  # 每个子进程里,发送10次数据
          print $sock  random() . "\n";
          select(undef, undef, undef, 0.25);  # 每发送一次,就休眠0.25秒
      }

      $sock->close or die $!;  # 发送完后关闭socket,并退出子进程
      exit 0;
   }
}

for (@childs) {  # 回收子进程
    my $tmp = waitpid($_, 0);
    print "done with pid $tmp\n";
}   

sub random {  # 该函数产生随机字串
    my @x=(0..9,'a'..'z','A'..'Z');
    join '',map {$x[int rand @x]} 1..49;  # 返回49字节长度的串
}


服务器端使用select复用模式

use strict;
use IO::Socket;
use IO::Select;

$|++;  # 因为print到终端,所以这里要打开autoflush
my $s = IO::Socket::INET->new(LocalAddr => 'localhost',  # 创建一个侦听socket
                              LocalPort => 1234,
                              Listen    => 5,
                              Proto     => 'tcp')
        or die $@;

my $read_set = new IO::Select();   # 创建一个IO::Select目标
$read_set->add($s);   # 把上述侦听socket加入IO::Select的检查队列

while (1) {   # 一个死循环
   # IO::Select有一个静态select方法,第一个参数如果设置,表示检查可读的socket
   # 该方法一直block,直到有可用的句柄返回
   # 返回一个三参数列表,第一个参数表示可读的socket句柄集合(一个数组引用)
  my ($rh_set) = IO::Select->select($read_set, undef, undef, undef);   

  foreach my $rh (@$rh_set) {  # 遍历可读的socket
     # 如果当前可读的socket等于侦听socket,那么说明有请求进来,应该及时accept
     # accept后,把已建立连接的socket句柄加入检查队列
     if ($rh == $s) {
        my $ns = $rh->accept();
        $read_set->add($ns);

     # 使用sysread读取数据,每次读取32字节,并且只处理这32字节
     # 如果客户端发送多于32字节的数据包,会分几次处理,如果几个客户端同时发送,处理过程是无序的
     # 避免使用<>方式读取socket,因为<>面向行读取,perlio对它做了缓冲,IO::Select看不到这个缓冲
     }else {
        my $buf = undef;
        if (sysread($rh,$buf,32)) {
            print $rh->fileno, " ", $buf, " ";

        # sysread的返回是读取的字节数量,如果返回0,则说明抵达文件末尾(EOF)
        # 如果sysread返回0,那么说明客户端关闭socket,我们从检查队列里删除该句柄,同时关闭socket句柄
        } else {
            print "no more data, close socket " . $rh->fileno . "\n";
            $read_set->remove($rh);
            $rh->close;
        }
     }
  }
}


下面使用coro来进行改造

 

 

<think>好的,用户想了解如何使用Folly库中的协程功能来开发服务端程序,需要教程或示例代码。首先,我需要回忆一下Folly库的协程模块的基本情况。Folly的coro是基于C++20协程的扩展,提供了异步操作的封装,适用于高并发场景。接下来,用户可能需要一个简单的示例来入门。我应该先写一个基本的协程函数,展示如何用folly::coro::Task来定义协程。比如,一个简单的echo服务器,接收客户端连接,然后异步读取数据并回传。同时,需要说明如何结合AsyncServerSocket和协程来处理连接。 然后,要注意代码的结构,确保使用正确的格式,比如独立公式用$$...$$,行内用$...$。不过这里主要是代码示例,所以可能需要用代码块来展示。同时,用户提到的系统级指令中的LaTeX语法正确,但这里可能不需要数学公式,但需要确保代码正确。 还需要考虑用户可能遇到的问题,比如如何编译、依赖项的处理,或者协程与现有异步框架的整合。因此,在回答中应该提到编译时需要链接的库,比如folly和fmt,以及C++17或更高版本的要求。 另外,用户可能需要了解协程在服务端应用中的优势,比如简化异步代码、提高可读性。可以对比传统的回调方式,说明协程如何避免回调地狱,提升维护性。生成的相关问题部分,需要考虑用户可能进一步询问的内容,比如性能优化、异常处理、超时机制,或者与其他库的集成。这些问题可以帮助用户深入理解Folly协程的实际应用。最后,检查引用部分,确保引用的示例或文档正确。例如,Folly的官方文档或GitHub仓库中的示例代码,可能需要添加引用标识,但用户提供的示例中没有具体引用来源,所以可能需要标注参考Folly官方资源。</think>以下是使用Folly协程开发服务端程序的实现示例和关键步骤说明: ### 一、基本协程服务端结构 ```cpp #include <folly/experimental/coro/Task.h> #include <folly/io/async/AsyncServerSocket.h> // 协程处理客户端连接 folly::coro::Task<void> handle_client(folly::AsyncTransportWrapper::UniquePtr sock) { char buf[1024]; while (true) { size_t len = co_await sock->asyncRead(buf, sizeof(buf)); if (len <= 0) break; co_await sock->asyncWrite(buf, len); } } // 异步接收连接的主协程 folly::coro::Task<void> server_coroutine(uint16_t port) { auto socket = folly::AsyncServerSocket::newSocket(); socket->bind(port); socket->listen(100); while (true) { auto client = co_await socket->co_accept(); folly::coro::co_invoke(handle_client(std::move(client))).scheduleOn( folly::getGlobalCPUExecutor()); } } ``` ### 二、关键实现机制 1. **协程调度**: - 使用`folly::coro::co_invoke`启动协程 - 通过`scheduleOn`指定执行器(如IO线程池) - 内置支持`folly::Executor`体系[^1] 2. **异步IO集成**: ```cpp // 异步读写示例 co_await socket->asyncRead(...); co_await socket->asyncWrite(...); ``` 3. **并发控制**: ```cpp // 批量并行处理 std::vector<folly::coro::Task<int>> tasks; tasks.push_back(co_await co_process(req1)); tasks.push_back(co_await co_process(req2)); auto results = co_await folly::coro::collectAllRange(std::move(tasks)); ``` ### 三、编译配置 需要添加以下编译选项: ```bash -std=c++20 -lfolly -lfmt ``` ### 四、性能优化建议 1. 使用`folly::coro::AsyncGenerator`处理流式数据 2. 通过`folly::coro::timeout`设置操作超时 3. 结合`folly::fibers::Baton`进行线程间同步
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
红包 添加红包
表情包 插入表情
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值