我只需要在 TCP 连接完全关闭后执行一些操作,也就是说 - 所有数据段以及完成例程(FIN-ACK 或 RST)都已执行并完成,并且不会有任何数据包在电线上发送。
由于closesocket()
不是同步的并且可以在连接和套接字完全关闭之前返回,我使用该SO_LINGER
选项来获取关闭的时刻。
根据 MSDN 中关于 closesocket 的说明,以及我的套接字是非阻塞的(因此是异步的)这一事实,我编写了以下代码:
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");
但是,closesocket 调用返回零(成功;而不是进入循环),我在 Wireshark 中看到我的最终打印是在所有数据包发送之前调用的,所以 - 看起来 linger 不起作用。
顺便说一句,我用来打开和连接异步套接字的函数是socket()
,WSAIoctl()
以及它的lpfnConnectEx()
回调。
在 TCP 连接完全完成之前,徘徊的 closesocket 返回的原因是什么?有解决办法吗?