这篇记录本来是准备和上一篇记录一起发的,但是感觉太长了。所以单独写开来了。
今早来的时候主程说服务器好像有问题,给了我一张截图:
我一看全是CLOSE_WAIT。就是说服务器被动关闭TCP链接。
写一下网上查到的:
CLOSE_WAIT 是被动关闭 TCP 连接时产生的,如果收到另一端关闭连接的请求后,本地(Server端)不关闭相应套接字就会导致本地套接字进入这一状态。(如果对方关闭了,没有收到关闭链接请求,就是下面的不正常情况)。
按TCP状态机,我方收到FIN,则由TCP实现发送ACK,因此进入CLOSE_WAIT状态。但如果我方不执行close(),就不能由CLOSE_WAIT迁移到LAST_ACK,则系统中会存在很多CLOSE_WAIT状态的连接。
如果存在大量的 CLOSE_WAIT,则说明客户端并发量大,且服务器未能正常感知客户端的退出,也并未及时 close 这些套接字。(如果不及时处理,将会出现没有可用的socket描述符的问题,原因是sockfd耗尽)。
正常情况下::
一方关闭sockfd,另外一方将会有读事件产生, 当recv数据时,如果返回值为0,表示对端已经关闭。此时我们应该调用close,将对应的sockfd也关闭掉。
不正常情况下::
一方关闭sockfd,另外一方并不知道,(比如在close时,自己断网了,对方就收不到发送的数据包)。此时,如果另外一方在对应的sockfd上写send或读recv数据。
recv时,将会返回0,表示链接已经断开。
send时, 将会产生错误,errno为ECONNRESET。
也就是说TCP的句柄耗尽,无法为新的链接提供句柄。所以产生了CLOSE_WAIT。现在的改法是在Client那面,让它收到我的数据后主动断开。这样就能能够有足够的句柄了。
详细参考的话可以看看<Unitx网络编程>这本书,最近也在看这本书,推荐给大家。