网络与通信程序设计(第2版)里EventSelect模型示例代码的一个bug

近几日在拜读王艳平老师的网络与通信程序设计(第2版),发现了一个示例代码的BUG.将会导致了winsock程序出现大量的CLOSE_WAIT状态.趁着机会写出来,留给后来学习的新人,大家共勉之.

关于socket关闭时出现CLOSE_WAIT状态的原因,网络上有很多高人分析的资料,大家有兴趣可以搜索一下.我就不班门弄斧了,总而言之一句话,是自身的winsock程序在处理关闭状态的时候没有处理好导致.

该书的51页中的HandleIO函数,原版代码如下:

 1 BOOL HandleIO(PTHREAD_OBJ pThread, PSOCKET_OBJ pSocket)
 2 {
 3     // 获取具体发生的网络事件
 4     WSANETWORKEVENTS event;
 5     ::WSAEnumNetworkEvents(pSocket->s, pSocket->event, &event);
 6     do
 7     {
 8         if(event.lNetworkEvents & FD_READ)            // 套节字可读
 9         {
10             if(event.iErrorCode[FD_READ_BIT] == 0)
11             {
12                 char szText[256];
13                 int nRecv = ::recv(pSocket->s, szText, strlen(szText), 0);
14                 if(nRecv > 0)                
15                 {
16                     szText[nRecv] = '\0';
17                     printf("接收到数据:%s \n", szText);
18                 }
19             }
20             else
21                 break;
22         }
23         else if(event.lNetworkEvents & FD_CLOSE)    // 套节字关闭
24         {
25             break;
26         }
27         else if(event.lNetworkEvents & FD_WRITE)    // 套节字可写
28         {
29             if(event.iErrorCode[FD_WRITE_BIT] == 0)
30             {    
31             }
32             else
33                 break;
34         }
35         return TRUE;
36     }
37     while(FALSE);
38 
39     // 套节字关闭,或者有错误发生,程序都会转到这里来执行
40     RemoveSocketObj(pThread, pSocket);
41     FreeSocketObj(pSocket);
42     return FALSE;
43 }

网络中经常有服务器为了避免大量FIN_WAIT1和TIME_WAIT状态的出现,设置socket为发送完数据立即强制关闭,这样就会导致很多socket的FD_CLOSE事件与最后一次FD_READ事件一起到达.因为event.lNetworkEvents是一个按位标识符,这里示例代码使用了else(红色标注)进行处理,所以在遇到这些强制关闭服务端的时候,将会对FD_CLOSE事件漏处理,从而导致大量的CLOSE_WAIT状态产生.

说到这里CLOSE_WAIT的解决办法已经出来了,将红色else部分全部删除,问题解决.

转载于:https://www.cnblogs.com/vikong2012/articles/2688706.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值