如何检查客户端是否已断开连接?
How to check if a client has disconnected?
我有一个简单的服务器套接字
my $server = IO::Socket::INET->new(
LocalPort => $config{'local-port'},
Reuse => 1,
Listen => 10,
Timeout => 1,
Blocking => 1
) or croak "Couln't start server: $!\n";
我想在客户端连接时继续执行一些例程
while (1) {
my $client = $server->accept;
next unless $client;
say "new connection";
# this loop never ends
while ( $client->connected ) {
# do_work();
}
say "connection closed";
}
但是$socket->connected
总是returntrue
(或者貌似直到tcp keepalive
没有发送)。
有没有办法检查客户端是否仍处于连接状态(例如,如果它在 10 秒内未发送任何内容,则可以认为已断开连接)?
Is there a way to check if client is still connected (for example if it didn't send anything in 10 seconds it can be considered disconnected)?
TCP 中的“断开连接”意味着已完成明确的 TCP 关闭。 10 秒内没有数据与此不同 - 期望应用程序每 10 秒发送一次数据,如果这没有发生,则出现问题,例如对等点崩溃或连接丢失。
要检测其中任何一个,有必要实际尝试从套接字中读取。在显式 TCP 断开连接的情况下,读取将 return 读取 0 个字节 w/o 任何失败。
这不同于打开连接但没有可用数据 - 此处读取将挂在阻塞套接字上,因此应首先使用 select 或类似方法检查是否有可读取的内容。或者使用 non-blocking 套接字,在这种情况下,读取将因 EWOULDBLOCK(或 EAGAIN,这在大多数 OS 上是相同的)而失败。
如果实际读取数据不符合程序的设计方式,也可以结合使用 select(检查是否读取了某些内容)和 MSG_PEEK 来检查套接字缓冲区和底层连接的状态,即像这样的东西:
vec(my $rin = '', fileno($socket), 1) = 1;
my $n = select($rin, undef, undef, undef, 0);
if ($n<0) {
# something wrong, socket likely already explicitly locally closed
} elsif ($n == 0) {
# read would block, i.e. no explicit disconnect and no data to read
} else {
$n = recv($socket, my $buf, 1, MSG_PEEK);
if ($n>0) {
# data available in socket buffer
} elsif ($n==0) {
# no data available and no errno -> socket closed by peer
} else {
# socket broken, for example keep alive timer failed
}
}
我有一个简单的服务器套接字
my $server = IO::Socket::INET->new(
LocalPort => $config{'local-port'},
Reuse => 1,
Listen => 10,
Timeout => 1,
Blocking => 1
) or croak "Couln't start server: $!\n";
我想在客户端连接时继续执行一些例程
while (1) {
my $client = $server->accept;
next unless $client;
say "new connection";
# this loop never ends
while ( $client->connected ) {
# do_work();
}
say "connection closed";
}
但是$socket->connected
总是returntrue
(或者貌似直到tcp keepalive
没有发送)。
有没有办法检查客户端是否仍处于连接状态(例如,如果它在 10 秒内未发送任何内容,则可以认为已断开连接)?
Is there a way to check if client is still connected (for example if it didn't send anything in 10 seconds it can be considered disconnected)?
TCP 中的“断开连接”意味着已完成明确的 TCP 关闭。 10 秒内没有数据与此不同 - 期望应用程序每 10 秒发送一次数据,如果这没有发生,则出现问题,例如对等点崩溃或连接丢失。
要检测其中任何一个,有必要实际尝试从套接字中读取。在显式 TCP 断开连接的情况下,读取将 return 读取 0 个字节 w/o 任何失败。
这不同于打开连接但没有可用数据 - 此处读取将挂在阻塞套接字上,因此应首先使用 select 或类似方法检查是否有可读取的内容。或者使用 non-blocking 套接字,在这种情况下,读取将因 EWOULDBLOCK(或 EAGAIN,这在大多数 OS 上是相同的)而失败。
如果实际读取数据不符合程序的设计方式,也可以结合使用 select(检查是否读取了某些内容)和 MSG_PEEK 来检查套接字缓冲区和底层连接的状态,即像这样的东西:
vec(my $rin = '', fileno($socket), 1) = 1;
my $n = select($rin, undef, undef, undef, 0);
if ($n<0) {
# something wrong, socket likely already explicitly locally closed
} elsif ($n == 0) {
# read would block, i.e. no explicit disconnect and no data to read
} else {
$n = recv($socket, my $buf, 1, MSG_PEEK);
if ($n>0) {
# data available in socket buffer
} elsif ($n==0) {
# no data available and no errno -> socket closed by peer
} else {
# socket broken, for example keep alive timer failed
}
}