perl – 如何使用具有端口重用的套接字的AnyEvent :: Handler
发布时间:2020-12-16 06:18:50 所属栏目:大数据 来源:网络整理
导读:最近我遇到了一个很棒的perl模块“AnyEvent”,它允许用户进行异步/事件驱动的编程. 创建了以下代码片段,工作正常.我遇到的问题是,在打开并关闭许多套接字后,它很快耗尽了所有客户端端口(“netstat -ant”显示20,000个套接字处于TIME_WAIT状态). $hdl = new A
最近我遇到了一个很棒的perl模块“AnyEvent”,它允许用户进行异步/事件驱动的编程.
创建了以下代码片段,工作正常.我遇到的问题是,在打开并关闭许多套接字后,它很快耗尽了所有客户端端口(“netstat -ant”显示20,000个套接字处于TIME_WAIT状态). $hdl = new AnyEvent::Handle ( connect => [$ip,$port],on_connect=> sub { my ($handle,$host,$port,$tmp) = @_; #print "connect routine for $handle->{ue}rn"; #update states. },on_read => sub { my $hdl = $_[0]; #read data #send response. }); 我想知道是否可以使用IO :: Socket :: INET创建TCP套接字,然后在AnyEvent :: Handle中使用新创建的套接字: my $sock = IO::Socket::INET->new( Proto => 'tcp',PeerAddr => $ue->{vars}->{ip},PeerPort => $ue->{vars}->{dstPort},ReusePort => 1,KeepAlive => 1 ) || die "failed to setup outsock $@n"; $hdl = new AnyEvent::Handle ( fh => $sock,on_read => sub { my $hdl = $_[0]; #read data #send response. }); 尝试过,但它不起作用.感谢任何建议/意见. 感谢ikegami调查并提出了建议.但是,似乎SO_REUSEADDR没有生效.这是我使用的代码(基于他的建议) use strict; use warnings; use AnyEvent qw( ); use AnyEvent::Handle qw( ); use AnyEvent::Impl::EV qw( ); use AnyEvent::Socket qw( tcp_connect ); use Socket qw( SOL_SOCKET SO_REUSEPORT SO_REUSEADDR); my $ts = 0; my $trans = 0; my $currentTS; sub transaction { my ($host,$port) = @_; tcp_connect($host,sub { my ($sock) = @_ or die "Can't connect: $!"; my $handle; $handle = AnyEvent::Handle->new( fh => $sock,on_eof => sub { $handle->destroy(); },on_read => sub { my ($handle) = @_; #print $handle->rbuf(); $trans ++; $currentTS = time(); if ($currentTS > $ts) { $ts = $currentTS; print "$transn"; } #printf "recved %d bytes of datan",length($handle->rbuf); # This should continue to read until header + # Content-Length bytes have been read instead # of stopping after one read. if (length($handle->rbuf) > 0) { $handle->destroy(); } },); $handle->push_write("GET /s HTTP/1.1rnHost: $hostrnrn"); #$handle->push_shutdown(); # Done writing. },sub { my ($sock) = @_; #setsockopt($sock,SOL_SOCKET,SO_REUSEPORT,1) or die $!; setsockopt($sock,SO_REUSEADDR,1) or die $!; # die "failed to set linger $!n"; return undef; }); } { my $cv = AnyEvent->condvar(); my $t = AnyEvent->timer(after=>0.001,interval=>1,cb=> sub { transaction("10.3.0.6",80 ); }); $cv->recv(); } 我的系统是Ubuntu 11.04.
解决方法
我无法运行以下内容,因为Windows不提供SO_REUSEPORT,但我非常确信以下内容可以满足您的要求.
那就是说,我不确定它会有所帮助.根据我的阅读,SO_REUSEPORT允许您绑定到已经活动的端口,但是您没有绑定到任何端口. use strict; use warnings; use AnyEvent qw( ); use AnyEvent::Handle qw( ); use AnyEvent::Impl::EV qw( ); use AnyEvent::Socket qw( tcp_connect ); use Socket qw( SOL_SOCKET SO_REUSEPORT ); ? sub transaction { my ($host,on_read => sub { my ($handle) = @_; print $handle->rbuf(); # This should continue to read until header + # Content-Length bytes have been read instead # of stopping after one read. $handle->destroy(); },); $handle->push_write("GET / HTTP/1.1rnHost: $hostrnrn"); $handle->push_shutdown(); # Done writing. },sub { my ($sock) = @_; setsockopt($sock,1) or die $!; return undef; }); } ? { my $cv = AnyEvent->condvar(); my $t = AnyEvent->timer(after=>0.001,interval=>0.001,cb=> sub { transaction("localhost",$ARGV[0] // die("usage")); }); $cv->recv(); } 用于测试的服务器: use strict; use warnings; use 5.010; use IO::Socket::INET qw( ); use Socket qw( inet_ntoa ); my $serv = IO::Socket::INET->new( Listen => 1,); say inet_ntoa($serv->sockaddr) . ":" . $serv->sockport; while (my $client = $serv->accept()) { say "Connection from ".inet_ntoa($client->peeraddr).":".$client->peerport; while (<$client>) { last if /^(?:r?n)?z/; } say $client "HTTP/1.1 200 OKrn" . "Content-Type: text/plainrn" . "rn" . "Hellon"; say " done."; } (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |