我有一個簡單的服務器套接字
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總是回傳true(或看似直到tcp keepalive未發送)。
有沒有辦法檢查客戶端是否仍然連接(例如,如果它在 10 秒內沒有發送任何內容,則可以認為它已斷開連接)?
uj5u.com熱心網友回復:
有沒有辦法檢查客戶端是否仍然連接(例如,如果它在 10 秒內沒有發送任何內容,則可以認為它已斷開連接)?
就 TCP 而言,“斷開連接”意味著已完成顯式 TCP 關閉。10 秒內沒有資料與此不同 - 期望應用程式每 10 秒發送一次資料,如果沒有發生這種情況,則出現問題,例如對等體崩潰或連接丟失。
要檢測其中任何一個,有必要實際嘗試從套接字讀取。在顯式 TCP 斷開連接的情況下,讀取將回傳讀取 0 位元組而沒有任何失敗。
這與打開連接但沒有可用資料不同 - 這里讀取將掛在阻塞套接字上,因此應首先使用select或類似方法檢查是否有要讀取的內容。或者使用非阻塞套接字,在這種情況下,讀取將因 EWOULDBLOCK(或 EAGAIN,在大多數作業系統上相同)而失敗。
如果實際讀取資料不符合程式設計的方式,也可以使用 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
}
}
轉載請註明出處,本文鏈接:https://www.uj5u.com/houduan/470780.html
