Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/perl/9.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181

Warning: file_get_contents(/data/phpspider/zhask/data//catemap/3/sockets/2.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Perl IO::套接字计时问题_Perl_Sockets - Fatal编程技术网

Perl IO::套接字计时问题

Perl IO::套接字计时问题,perl,sockets,Perl,Sockets,我碰到了一个奇怪的问题。我用Perl编写了一个小守护程序,它绑定服务器上的一个端口。 在同一台服务器上,有一个LAMP正在运行,我的Perl守护进程的客户端是一个php文件,它打开一个带有守护进程的套接字,推送一些信息,然后关闭连接。在Perl守护进程中,我将每个连接记录在一个日志文件中,供以后使用 我最大的问题是:从php脚本完成执行的那一刻起,守护进程记录连接需要15-20秒 PHP客户端: $sh = fsockopen("127.0.0.1", 7890, $errno, $errstr

我碰到了一个奇怪的问题。我用Perl编写了一个小守护程序,它绑定服务器上的一个端口。 在同一台服务器上,有一个LAMP正在运行,我的Perl守护进程的客户端是一个php文件,它打开一个带有守护进程的套接字,推送一些信息,然后关闭连接。在Perl守护进程中,我将每个连接记录在一个日志文件中,供以后使用

我最大的问题是:从php脚本完成执行的那一刻起,守护进程记录连接需要15-20秒

PHP客户端:

$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;

        }

}