2

I need to perform some operations only after the time a TCP connection is fully closed, that's to say - all the data segments, as well as the finishing routine (FIN-ACK or RST) have been performed and done, and no packets will be sent on the wires.

Since closesocket() is not synchronous and could return before a full close of the connection and socket, I've used the SO_LINGER option to get the moment of closing.

According to the instructions in the MSDN for closesocket, and to the fact that my socket is non-blocking (and thus asynchronous), I wrote this code:

int ret;

/* config 2 secs of linger */
struct linger lng = {1, 2};
setsockopt(s, SOL_SOCKET, SO_LINGER, (const char*)&lng, sizeof(lng));

/* graceful close of TCP (FIN-ACK for both sides) */
shutdown(s, SD_BOTH);

/* linger routine for asynchronous sockets according to msdn */
do {

     ret = closesocket(s);

} while (ret == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK);

/* my code to be run immediately after all the traffic */
printf("code to run after closing");

However, the closesocket call returns zero (success; instead of getting into the loop) and I see in Wireshark that my final printing is called before all the packets were sent, so - it looks like the linger isn't working.

By the way, the functions I used to open and connect the asynchronous socket were socket(), WSAIoctl() and its lpfnConnectEx() callback.

What's the reason that the lingered closesocket return before a full finish of the TCP connection? Is there a solution?

Reflection
  • 1,936
  • 3
  • 21
  • 39
  • 1
    [This page might answer some of your questions](http://blog.netherlabs.nl/articles/2009/01/18/the-ultimate-so_linger-page-or-why-is-my-tcp-not-reliable). To be honest, maybe you should have the remote end respond with an ACK to acknowledge receipt of the data, and then after receiving that then close down and proceed. – Cornstalks Apr 20 '15 at 16:26
  • Besides the fact that the final solution is offered only to Linux, I tried to add a send() and recv() waiting before closesocket(), but it didn't solve the problem. – Reflection Apr 20 '15 at 16:34
  • Once you finished writing to a socket, you have to send FIN via shutdown(SHUT_WR) and then wait for remaining data/FIN-ACK/RST via read() until it returns <= 0. This is what we call "graceful close". If you read without a shutdown, peer can't know that it's all over and will also block in read-loop thus causing a deadlock (unless your explicitly sent him an app-level termination sequence or max-length so it can initiate shutdown by itself). – user3125367 Apr 21 '15 at 01:19
  • If you close socket without read until it returns <= 0, you're entering net race condition where graceful close may not happen, as described in the article. – user3125367 Apr 21 '15 at 01:23
  • As I said, I tried to wait for recv() but a final ACK to a FIN-ACK is sent after my printing. – Reflection Apr 21 '15 at 08:12
  • Someone, solution? :( – Reflection Apr 24 '15 at 11:54
  • How can you see your final printing in Wireshark? It doesn't go there. – user207421 Jul 29 '18 at 06:10

0 Answers0