下面,测试多进程:
###server
use IO::Socket;
my $quit = 0;
$SIG{INT} = sub { $quit++ }; #当程序中断时,比如 ctrl+C 发送此信号,定义处理函数为$quit自增
my $server = IO::Socket::INET->new(LocalPort => '65432',
Listen =>2,
Resue => 1)
or die “cannot listenon port : $@”;
while ( ! $quit ) # 当程序未中断时
{
next unless my $client = $server->accept() ;
my $child = fork(); #fork产生子进程
if ( $child == 0 )
{
#子进程执行内容
$server->close;
while (<$client>)
{
print “client : $_”;
print $client “hello $_”;
}
}
#父进程执行
$client->close;
}
###client
use IO::Socket;
my $sock = IO::Socket::INET->new(PeerAddr => 'localhost',
PeerPort => '65432',
Proto => 'tcp')
or die “cannot connet: $@”;
while( <STDIN>)
{
print $sock $_;
my $msg = <$sock>;
print “server : $_”;
}
说明:
1. 声明信号处理匿名函数用于在程序捕获到信号后执行自定义的动作,这里自增变$quit量用于控制后面跳出while循环;因此如果有意设计,可以屏蔽如ctrl+c ctrl+z等动作,使脚本无法退出。
比如定义匿名函数处理$SIG{INT} = $SIG{TSTP}
2. 可以这样理解,从fork执行的那一刻开始,系统中产生两个相同的副本,每一个都按照脚本正常逻辑继续执行。区别在于fork对它们返回值不同,在主进程返回子进程pid,在子进程返回0。因此通过返回值来控制父进程和子进程执行不同内容的动作;
3. 当fork发生后,父进程和子进程均拥有$server和$client这两个socket对象。为相互保持独立,在父进程中继续监听,所以将$client连接关闭;子进程将监听$server关闭。
运行测试:
首先启动server端,再启动一个客户端
tcp 0 0 0.0.0.0:65432 0.0.0.0:* LISTEN
tcp 0 0 192.168.10.15:65432 192.168.10.16:40448 ESTABLISHED
接着再启动一个客户端
tcp 0 0 0.0.0.0:65432 0.0.0.0:* LISTEN
tcp 0 0 192.168.10.15:65432 192.168.10.16:40448 ESTABLISHED
tcp 0 0 192.168.10.15:65432 192.168.10.16:40449 ESTABLISHED
此时后台进程
appmon 5457 4927 0 21:01 pts/1 00:00:00 perl t_server.plx
appmon 5460 5457 0 21:01 pts/1 00:00:00 perl t_server.plx
appmon 5469 5457 0 21:02 pts/1 00:00:00 perl t_server.plx
通过命令lsof -Pnl +M -i4 | grep 65432 可以查看到父进程 5457 正处在监听状态,其他两个子进程处于连接状态
perl 5457 500 3u IPv4 17984 TCP *:65432 (LISTEN)
perl 5460 500 4u IPv4 17985 TCP 192.168.10.15:65432->192.168.10.16:40448 (ESTABLISHED)
perl 5469 500 4u IPv4 18009 TCP 192.168.10.15:65432->192.168.10.16:40449 (ESTABLISHED)