Perl IO::套接字计时问题
我碰到了一个奇怪的问题。我用Perl编写了一个小守护程序,它绑定服务器上的一个端口。 在同一台服务器上,有一个LAMP正在运行,我的Perl守护进程的客户端是一个php文件,它打开一个带有守护进程的套接字,推送一些信息,然后关闭连接。在Perl守护进程中,我将每个连接记录在一个日志文件中,供以后使用 我最大的问题是:从php脚本完成执行的那一刻起,守护进程记录连接需要15-20秒 PHP客户端:Perl IO::套接字计时问题,perl,sockets,Perl,Sockets,我碰到了一个奇怪的问题。我用Perl编写了一个小守护程序,它绑定服务器上的一个端口。 在同一台服务器上,有一个LAMP正在运行,我的Perl守护进程的客户端是一个php文件,它打开一个带有守护进程的套接字,推送一些信息,然后关闭连接。在Perl守护进程中,我将每个连接记录在一个日志文件中,供以后使用 我最大的问题是:从php脚本完成执行的那一刻起,守护进程记录连接需要15-20秒 PHP客户端: $sh = fsockopen("127.0.0.1", 7890, $errno, $errstr
$sh = fsockopen("127.0.0.1", 7890, $errno, $errstr, 30);
if (!$sh)
{
echo "$errstr ($errno)<br />\n";
}
else
{
$out = base64_encode('contents');
fwrite($sh, $out);
fclose($sh);
}
$sh=fsockopen(“127.0.0.1”,7890,$errno,$errstr,30);
如果(!$sh)
{
回显“$errstr($errno)
\n”;
}
其他的
{
$out=base64_编码(“内容”);
fwrite($sh,$out);
fclose(瑞典元);
}
Perl守护进程(只是套接字部分)
#/usr/bin/perl
严格使用;
使用警告;
使用Proc::Daemon;
使用Proc::PID::File;
使用IO::Socket;
使用MIME::Base64;
使用Net::Address::IP::Local;
主要内容:
{
#设置要向下使用的一些变量。。。
如果(Proc::PID::File->running())
{
出口(0);
}
my$sock=新IO::Socket::INET(
LocalHost=>$ip,
LocalPort=>$port,
Proto=>“tcp”,
Listen=>SOMAXCONN,
重用=>1);
$sock或die“无插座:$!”;
我的($new_sock,$c_addr,$buf);
对于(;;)
{
#安装日志文件
打开(左侧,“>>”$日志);
打印“服务器启动于$ip:$port\n”;
打印LH“服务器在$ip:$port上启动\n”;
而(($new\u sock,$c\u addr)=$sock->accept())
{
我的($client_port,$c_ip)=sockaddr_in($c_addr);
我的$client_ipnum=inet_ntoa($c_ip);
我的$client\u host=gethostbyaddr($c\u ip,AF\u INET);
my($sec、$min、$hour、$mday、$mon、$year、$wday、$yday、$isdst)=本地时间;
$year+=1900;
$mon+=1;
打印“$year-$mon-$mday$hour:$min:$sec[”.time()。“]-从以下位置获得连接:[$client_ipnum]”;
打开(AL,“>>”$accessLog);
打印所有“$year-$mon-$mday$hour:$min:$sec[”.time()。“]-从以下位置获得连接:[$client_ipnum]\n”;
封闭AL;
while(已定义($buf=))
{
打印“内容:”,解码base64($buf),“\n”;
打开(FH,“>”$basepath.“文件”..time().“.txt”)或警告“无法打开”$basepath.“文件”..time().“.txt以便写入:$!”;
打印FH解码基64($buf);
关闭FH;
}
}
关闭左侧;
}
}
我做错了什么,然后导致php在编写套接字后关闭套接字和Perl脚本记录连接之间有20秒的间隔。有什么想法吗?
请温和一点,我是Perl新手:)我没有看到任何刷新缓冲区的调用,您能检查一下日志记录后刷新时延迟是否消失吗?$new\u sock没有显式关闭,因此在接受调用之前不会关闭。这可能会导致某些内容挂起,直到达到超时。(我不确定是否会在进入接受或退出时关闭。) 此外,您正在使用“”运算符从套接字读取数据。如果输入中没有换行符会发生什么
查看实际情况的最佳方法是在“strace-e trace=network”下运行进程,并尝试将网络系统调用与perl和php语句相匹配。我在日志记录后尝试刷新,但没有得到任何改进。也许我写的Perl代码不好?Flush没有什么坏处。在PHP端,套接字什么时候真的超出了范围?在PHP端,我只是将数据写入套接字并关闭它。一切都很好,我用tcmpdump检查过了,一切都正常,只是perl守护进程在控制台(在关闭daemonize的情况下运行它进行开发)或日志文件中的写入滞后。如果我是你,我会在循环中添加更多的debug prints()。仅仅从代码上看,它可能会打印FH正在缓冲,或者可能没有及时关闭并且卡在循环中。或者可能一切正常,但日志记录被延迟了?这是真的:)我在big while结束之前关闭了$new_套接字,一切正常。如果我将要发送的内容的长度作为“第一行”发送,您能告诉我一个更好的方法来读取客户端的内容吗?谢谢我认为您的服务器存在一些基本问题:例如,我不知道它如何一次处理多个连接。最简单的方法是在accept之后fork(),处理子级中的所有IO,并在完成时退出:google for“perl cookbook”和forking服务器。对于读取数据,我倾向于使用read()或sysread(),这取决于我是否使用缓冲。谢谢你提供的信息:)我下一步将解决分叉问题。当时我决定买$new_sock->recv();用于从客户端读取数据。谢谢你的支持!
#!/usr/bin/perl
use strict;
use warnings;
use Proc::Daemon;
use Proc::PID::File;
use IO::Socket;
use MIME::Base64;
use Net::Address::IP::Local;
MAIN:
{
#setup some vars to be used down...
if (Proc::PID::File->running())
{
exit(0);
}
my $sock = new IO::Socket::INET(
LocalHost => $ip,
LocalPort => $port,
Proto => 'tcp',
Listen => SOMAXCONN,
Reuse => 1);
$sock or die "no socket :$!";
my($new_sock, $c_addr, $buf);
for (;;)
{
# setup log file
open(LH, ">>".$logs);
print "SERVER started on $ip:$port \n";
print LH "SERVER started on $ip:$port \n";
while (($new_sock, $c_addr) = $sock->accept())
{
my ($client_port, $c_ip) =sockaddr_in($c_addr);
my $client_ipnum = inet_ntoa($c_ip);
my $client_host =gethostbyaddr($c_ip, AF_INET);
my ($sec,$min,$hour,$mday,$mon,$year,$wday,$yday,$isdst) = localtime time;
$year += 1900;
$mon += 1;
print "$year-$mon-$mday $hour:$min:$sec [".time()."] - got a connection from: [$client_ipnum]";
open(AL, ">>".$accessLog);
print AL "$year-$mon-$mday $hour:$min:$sec [".time()."] - got a connection from: [$client_ipnum]\n";
close AL;
while (defined ($buf = <$new_sock>))
{
print "contents:", decode_base64($buf), " \n";
open(FH, ">".$basepath."file_" . time() .".txt") or warn "Can't open ".$basepath."file_".time().".txt for writing: $!";
print FH decode_base64($buf);
close FH;
}
}
close LH;
}
}