如何诊断“无法确定对等地址”在我的 Perl TCP 脚本中?
我有这个小脚本,它的工作做得很好,但有时它往往会失败。它在两种情况下失败:
发送错误:
无法确定 ./tcp-new.pl 第 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);
}
}
}
}
I've this little script which does it's job pretty well but sometimes it tends to fail. It fails in 2 cases:
with error send:
Cannot determine peer address at ./tcp-new.pl line 52
with no output or anything, it just fails to deliver what it got to connected Tcp Client. Usually it happens after I disconnect from server, go home and connect it again. To fix this restart is required and it starts working. Sometimes this problem is followed by problem mentioned in point 1.
Note: it's not problem when I disconnect and reconnect to it again within short amount of time (unless error nr 1 happens).
So can anyone help me make this code be a bit more stable so I don't have to restart it every day?
#!/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);
}
}
}
}
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(3)
无法确定对等地址
错误意味着getpeername()
返回 false。这可能意味着套接字已从另一侧关闭,可能在can_write()
调用和发送
调用。您可能应该将其从选择集中删除并继续。The
Cannot determine peer address
error means that thegetpeername()
returned false. This probably means that the socket has been closed from the other side, possibly between thecan_write()
call and thesend
call. You should probably remove it from the select set and move on.发现同样的问题,袜子没有对等地址。
在 http://search.cpan 上查看 IO::Socket。 org/src/GBARR/IO-1.2301/IO/Socket.pm 显示:
因此,您必须注意在对象创建时初始化对等名称,或者将对等地址作为 send() 的第三个参数提供。
Found the same issue, with the sock not having a peeraddress.
Looking into IO::Socket at http://search.cpan.org/src/GBARR/IO-1.2301/IO/Socket.pm reveals:
So you have to take care that either peername is initialized on object creation, or provided the peer address as a third argument to send().
在脚本完全失败且没有任何错误消息的情况下,可能是由于未处理的信号(通常是 SIGPIPE)造成的。如果套接字操作在发送操作期间收到信号,则可能会发生这种情况。通过模拟与 TCP 服务器的许多高数据量并发连接并同时终止这些客户端连接,我可以在自己的系统中轻松地重现它。在你的脚本上运行 strace,你可以清楚地看到信号。也就是说,我试图找出如何重现“无法确定对等地址”错误,但无济于事......
In the scenario where your script fails outright, without any error messages, it is probably due to an unhandled signal, usually a SIGPIPE. This can happen if socket operation gets a signal during a send operation. I can reproduce it easily enough in my own systems by simulating many high data volume concurrent connections to a tcp server and simultaneously killing those client connections. Run strace on your script, and you can see the signal clearly enough. That said, I'm trying to figure out how to reproduce the "Cannot determine peer address" error but to no avail....