Perl Fork实现TCP Server无法接收客户端多数据包问题求助
Perl多客户端TCP服务器:修复无法接收后续数据包的问题
问题说明
当前基于fork实现的TCP服务器可接受多客户端连接,但存在以下缺陷:
- 客户端能正常建立连接
- 首次发送的数据包可被接收打印
- 客户端保持连接发送的后续数据包无法被接收
核心原因是子进程仅执行一次recv就退出,没有持续监听客户端的数据流。以下是调整后的代码,实现客户端持续发送数据时,服务器能接收每个数据包并回复。
修改后的代码
#!/usr/bin/perl -w use IO::Socket::INET; use POSIX ':sys_wait_h'; # 引入WNOHANG常量 $SIG{CHLD} = sub { # 非阻塞回收子进程,避免僵尸进程 while ((my $pid = waitpid(-1, WNOHANG)) > 0) {} }; my $socket = new IO::Socket::INET ( LocalHost => '0.0.0.0', LocalPort => '5000', Proto => 'tcp', Listen => 10, # 支持至少10个等待连接的客户端 Reuse => 1 ); die "cannot create socket $!\n" unless $socket; while (my $new_sock = $socket->accept()) { my $pid = fork(); die "Cannot fork: $!" unless defined($pid); if ($pid == 0) { # 子进程负责处理单个客户端连接 $socket->close(); # 子进程无需持有监听socket,立即关闭 while (1) { my $data; # 接收客户端数据,返回值为接收的字节数 my $bytes_recv = $new_sock->recv($data, 500); # 客户端断开连接(recv返回undef或0)时退出循环 last unless defined $bytes_recv && $bytes_recv > 0; chomp $data; print "Received: $data\n"; # 向客户端发送回复 my $response = "Server ack: $data\n"; $new_sock->send($response); } $new_sock->close(); # 关闭客户端连接 exit(0); # 子进程正常退出 } else { $new_sock->close(); # 父进程无需持有客户端连接,立即关闭 } }
关键修改点
- 持续监听数据流:在子进程中添加
while(1)循环,让子进程持续调用recv接收客户端数据,直到连接断开 - 连接状态判断:通过
recv的返回值判断客户端是否断开,避免无限阻塞 - 回复逻辑:新增
send调用,实现服务器对每个数据包的回复 - 资源优化:父/子进程分别关闭不需要的socket,避免资源泄漏;改进子进程回收逻辑,防止僵尸进程
- 满足连接需求:将
Listen参数调整为10,支持至少10个等待连接的客户端
内容的提问来源于stack exchange,提问作者Lucas Rey
相关产品推荐
相关产品推荐

