該應用程序的目的是偵聽特定的UDP多播,然後將數據轉發給連接到服務器的任何TCP客戶端。該代碼工作正常,但我有問題的TCP客戶端斷開後,套接字不關閉。 socketsniffer實用程序顯示套接字保持打開狀態,並且所有UDP數據繼續被轉發給客戶端。我相信問題在於「if($ write-> connected())」塊,因爲它總是返回true,即使TCP客戶端不再連接。我使用標準Windows Telnet連接到服務器並查看數據。當我關閉telnet時,假設TCP套接字在服務器上關閉。如果客戶端不再連接,Perl不關閉TCP套接字?
爲什麼connect()將連接顯示爲活動連接的任何原因,即使它們不是?另外,我應該使用什麼替代方案?
代碼:
#!/usr/bin/perl
use IO::Socket::Multicast;
use IO::Socket;
use IO::Select;
my $tcp_port = "4550";
my $tcp_socket = IO::Socket::INET->new(
Listen => SOMAXCONN,
LocalAddr => '0.0.0.0',
LocalPort => $tcp_port,
Proto => 'tcp',
ReuseAddr => 1,
);
use Socket qw(IPPROTO_TCP TCP_NODELAY);
setsockopt($tcp_socket, IPPROTO_TCP, TCP_NODELAY, 1);
use constant GROUP => '239.2.0.81';
use constant PORT => '6550';
my $udp_socket= IO::Socket::Multicast->new(Proto=>'udp',LocalPort=>PORT);
$udp_socket->mcast_add(GROUP) || die "Couldn't set group: $!\n";
my $read_select = IO::Select->new();
my $write_select = IO::Select->new();
$read_select->add($tcp_socket);
$read_select->add($udp_socket);
## Loop forever, reading data from the UDP socket and writing it to the
## TCP socket(s).
while (1) {
## No timeout specified (see docs for IO::Select). This will block until a TCP
## client connects or we have data.
my @read = $read_select->can_read();
foreach my $read (@read) {
if ($read == $tcp_socket) {
## Handle connect from TCP client. Note that UDP connections are
## stateless (no accept necessary)...
my $new_tcp = $read->accept();
$write_select->add($new_tcp);
}
elsif ($read == $udp_socket) {
## Handle data received from UDP socket...
my $recv_buffer;
$udp_socket->recv($recv_buffer, 1024, undef);
## Write the data read from UDP out to the TCP client(s). Again, no
## timeout. This will block until a TCP socket is writable.
my @write = $write_select->can_write();
foreach my $write (@write) {
## Make sure the socket is still connected before writing.
if ($write->connected()) {
$write->send($recv_buffer);
}
else {
$write_select->remove($write);
close $write;
}
}
}
}
}
即使檢查零字節的讀寫,也不會告訴你TCP套接字是否仍然連接,而不知道另一端有什麼(例如,當我發送「foo」時,我總是會收到「bar 「在3秒內)。 – mob 2010-04-28 19:16:57
讀或寫完成時讀取或寫入的零字節會告訴您另一端發送FIN。你是對的,在沒有保持聯繫的情況下,不可能確定另一端是否已經離開而不關閉連接。 – Stewart 2010-04-28 19:56:06