Вам необходимо закрыть свой конец сокета, чтобы клиент знал, что данных больше не будет. Вам также необходимо прочитать все ожидающие данные, потому что, если вы сразу же вызовете Close()
, клиент получит сброс (TCP RST).
С помощью приведенного выше кода, как только клиент закроет свой конец или истечет указанное вами время ожидания, соединение будет окончательно закрыто на нашем конце.
То, что я делал давным-давно, было так (для сервера Mono ASP.NET ):
void LingeringClose ()
{
int waited = 0;
if (!Connected)
return;
try {
Socket.Shutdown (SocketShutdown.Send);
DateTime start = DateTime.UtcNow;
while (waited < max_useconds_to_linger) {
int nread = 0;
try {
if (!Socket.Poll (useconds_to_linger, SelectMode.SelectRead))
break;
if (buffer == null)
buffer = new byte [512];
nread = Socket.Receive (buffer, 0, buffer.Length, 0);
} catch { }
if (nread == 0)
break;
waited += (int) (DateTime.UtcNow - start).TotalMilliseconds * 1000;
}
} catch {
// ignore - we don't care, we're closing anyway
}
}