TCP是半关闭的,我在客户端使用以下方法关闭:
shutdown(sock, SD_BOTH);
closesocket(sock);
期望的是服务端连接也主动关闭,不再调用一次关闭操作。
但从状态上看客户端一直处理在FIN_WAIT_2状态,服务端处在CLOSE_WAIT状态。
监控报文的确是只有客户端发送了FIN/ACK。
如何才能只在客户端调用一次关闭就能关闭两个方向的连接呢?
shutdown(sock, SD_BOTH);
closesocket(sock);
期望的是服务端连接也主动关闭,不再调用一次关闭操作。
但从状态上看客户端一直处理在FIN_WAIT_2状态,服务端处在CLOSE_WAIT状态。
监控报文的确是只有客户端发送了FIN/ACK。
如何才能只在客户端调用一次关闭就能关闭两个方向的连接呢?
应该没有其它事情处理吧(服务器端)?!
因为在关闭前socket还有没传输完的数据。
方法1:完美关闭
A.保证socket中已经没有数据需要接收(可以peek一下socket是否还有数据存在系统缓冲),如果还有数据,先接完,然后用shutdown(),再使用closesocket(),如果没数据了,还是一样。方法2:强硬关闭
setsockopt()设置SO_LINGER去关闭,这样做就是在closesocket()时如果socket缓冲还残留有数据也会忽略,直接释放掉socket
例如我有一段程序,经测试并没有关闭,程序运行知道本身死掉(机器没有死掉):
lig.l_onoff=0;
lig.l_linger=0;
iLen=sizeof(struct linger);
setsockopt(GPRS_SOCKETS[j].sockid,SOL_SOCKET,SO_LINGER,(char *)&lig,iLen);
closesocket(GPRS_SOCKETS[j].sockid);
例如我有一段程序,经测试并没有关闭,程序运行直到本身死掉(机器没有死掉):
lig.l_onoff=0;
lig.l_linger=0;
iLen=sizeof(struct linger);
setsockopt(GPRS_SOCKETS[j].sockid,SOL_SOCKET,SO_LINGER,(char *)&lig,iLen);
closesocket(GPRS_SOCKETS[j].sockid);
假如我要创建一个线程监控每个socket,发现有一定时间没有通讯,我就要强制关闭该socket.
怎么能在accept之前关闭??
但是我还是不太明白:为什么要在accept后关闭?还有,假如我采用的是WSAAsyncSelect模型,那么accept是在 case FD_ACCEPT分支中建立socket连接,在该分支中,如何判断要关闭哪一个socket?也就是说,已经有多个socket,如何判断出要关闭某个长时间没有通讯的socket?
关于如何判断长时间没有通讯的socket,要上层自己做心跳检测,socket有keep-alive属性可以设置,但是不建议使用,心跳机制是tcp程序所必须的
Sleep(800);closesocket(sock); //关闭 套接
//将发送FIN,以关闭连接
shutdown(client, 1);
Sleep(600); //适当延时
closesocket(client);
//中止Windows Sockets DLL的使用
WSACleanup();
还有好像有点跑题了,我在上面说的设置linger也只是为了防止出现close_wait,并且据我理解,做了shutdown以后linger设置就无意义了,因为设置linger为0的目的就是为了不发FIN而直接RESET.
呵呵,我现在也不知道楼主想问的是什么了。