Gracefully shut down a TCP socket
Asked Answered
E

1

7

I'm writing an IRC client in C++ and currently I'm having an issue where, upon exit, I do:

Send("QUIT :Quit\r\n"); // just an inline, variadic send() wrapper
shutdown(m_hSocket, SD_BOTH);
closesocket(m_hSocket);

WSAShutdown();

However, the issue is that the QUIT message is not being sent. I've sniffed the packets coming from the client and infact this message is never sent. I believe this is an issue with the socket not being flushed, but I have no idea how to do this and Google suggested disabling Nagle's algorithm but I doubt this is good practice.

Thanks in advance.

Eddra answered 17/4, 2011 at 21:32 Comment(4)
For when you do get this working, remember that some IRC networks will not show a custom quit message until you have been signed in for > 5 minutes (the actual length varies depending on network). It's not an answer to your current problem, but it's a gotcha that can be confusing later on :)Refusal
Interesting point, but I've had it up for a couple of ours now, quit, and still got: Read error: Connection reset by peerEddra
yup, I just thought I'd mention it for when you get the socket issue fixed :)Refusal
There is no flush operation on sockets. Small data is collected for about 40ms and then send. Its called Naggle algorithm.Lefler
L
6

First of all you should check the return value of send: are the data you attempt to send actually accepted by the network stack? (In general this should be done after each and every send call, not just in this case).

Assuming the data is accepted, then AFAIK it should be actually transmitted as a result of calling shutdown. You might try using SO_LINGER to see if it makes a difference, see Graceful Shutdown, Linger Options, and Socket Closure on MSDN.

Lenka answered 17/4, 2011 at 22:36 Comment(2)
Even using the fix in the comments of that MSDN article, I still get the error when closing sockets at exit. It seems WSACleanup() causes it. Thanks anyway Jon! :DEddra
After calling shutdown(), you should not call closesocket() until after the remote peer has acknowledged the disconnect request, by calling recv() in a loop (optionally with select() to know when to call recv()) until it returns 0 (or an error).Azar

© 2022 - 2024 — McMap. All rights reserved.