You need to shutdown your end of the socket so the client knows there will be no more data. You also need to read any pending data because if you call Close()
right away the client will get a reset (TCP RST).
With the code above, once the client closes its end or the timeout you define is up, the connection will finally be closed on our end.
What I did a long time ago was this (for Mono's ASP.NET server):
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
}
}