我有这个小脚本,它的工作做得很好,但有时它往往会失败。它在两种情况下失败:
发送错误:Cannot determine peer address at ./tcp-new.pl line 52
没有输出或任何东西,它只是无法提供连接到Tcp客户端的内容。通常它发生在我与服务器断开连接后,回家再次连接。要修复此重新启动是必需的,它开始工作。有时这个问题之后是第1点中提到的问题。
注意:当我在短时间内再次断开连接并重新连接时(除非发生错误nr 1),这不是问题。
所以任何人都可以帮助我使这段代码更稳定,所以我不必每天都重启它吗?
#!/usr/bin/perl
use strict;
use warnings;
use IO::Socket;
use IO::Select;
my $tcp_port = "10008";
my $udp_port = "2099";
my $tcp_socket = IO::Socket::INET->new(
Listen => SOMAXCONN, LocalPort => $tcp_port,
Proto => 'tcp', ReuseAddr => 1,
);
my $udp_socket = IO::Socket::INET->new(
LocalPort => $udp_port, Proto => 'udp',
);
my $read_select = IO::Select->new();
my $write_select = IO::Select->new();
$read_select->add($tcp_socket);
$read_select->add($udp_socket);
while (1) {
my @read = $read_select->can_read();
foreach my $read (@read) {
if ($read == $tcp_socket) {
my $new_tcp = $read->accept();
$write_select->add($new_tcp);
} elsif ($read == $udp_socket) {
my $recv_buffer;
$udp_socket->recv($recv_buffer, 1024, undef);
my @write = $write_select->can_write();
foreach my $write (@write) {
$write->send($recv_buffer);
}
}
}
}
答案 0 :(得分:2)
Cannot determine peer address
错误表示getpeername()
返回false。这可能意味着套接字已从另一侧关闭,可能在can_write()
呼叫和send
呼叫之间。你可能应该从选择集中删除它并继续前进。
答案 1 :(得分:1)
发现同样的问题,袜子没有穿着。
在http://search.cpan.org/src/GBARR/IO-1.2301/IO/Socket.pm处查看IO :: Socket显示:
sub send { @_ >= 2 && @_ <= 4 or croak 'usage: $sock->send(BUF, [FLAGS, [TO]] +)';
my $sock = $_[0]; my $flags = $_[2] || 0; my $peer = $_[3] || $sock->peername;
croak 'send: Cannot determine peer address' unless($peer);
因此,您必须注意在创建对象时初始化peername,或者将peer地址作为send()的第三个参数。
if (! $sock->peeraddr()) {
$log->warn("No peer, will croak!");
}
答案 2 :(得分:0)
在脚本完全失败的情况下,没有任何错误消息,可能是由于未处理的信号,通常是SIGPIPE。如果套接字操作在发送操作期间获得信号,则会发生这种情况。通过模拟与tcp服务器的许多高数据量并发连接并同时终止这些客户端连接,我可以在我自己的系统中轻松地重现它。在脚本上运行strace,您可以清楚地看到信号。也就是说,我试图找出如何重现“无法确定对等地址”的错误,但无济于事....