阻塞socket和非阻塞socket(二)

非阻塞socket:

一般在项目中我们很多情况下都是有多个socket传输数据,而管理多个socket有几种I/O模型。如select模型、WSAAsyncSelect模型、WSAEventSelect模型、Overlapped I\O模型、完成端口等等。

根据项目的具体的情况选择相应的I\O模型。我在项目中用到最多的就是WSAAsyncSelect模型、WSAEventSelect模型这两种模型。这两种模型在管理socket的接收和关闭的时机是我们的重点考虑对象。而socket的接收和关闭依赖于FD_READ网络事件和FD_CLOSE网络事件。WSAAsyncSelect模型、WSAEventSelect模型会分别调用WSAAsyncSelect()和WSAEventSelect来注册socket感兴趣的网络事件,把这些网络事件分别绑定到对应的窗口消息和事件上。所以FD_READ网络事件和FD_CLOSE网络事件会影响我们的socket的数据接收和socket的关闭。下面通过实验结果来讨论这两个网络事件的产生时机。

1.FD_READ事件的产生与socket里的数据量和是否调用了recv函数有关。

2.在有新数据到达socket时会触发FD_READ.(不管你调不调用recv读,只要数据到达就会触发FD_READ)

3.在调用recv函数成功后,即recv函数的返回值不等于-1,并且socket缓冲区里还有数据,才会触发FD_READ.(如果调用recv成功后,把数据读完了,socket缓冲区里没有数据了,此时就不再触发FD_READ。在缓冲区里没数据,或数据没有准备好时,调用recv函数会出错,返回-1,这时也不会触发FD_READ.)

4.在缓冲区里有数据时,即使你调用了recv返回的是0,即你没有读出数据,但是调用成功了(比如把bufflen参数的值赋为0),这也会触发FD_READ.

5.在优雅的关闭发送端的socket时(调用closesocket函数),接受端会收到FD_CLOSE事件。此时还可以调用recv函数读取socket缓冲区里剩余的数据,这一点要特别注意,可以防止丢失数据。

6.在粗鲁的关闭发送端的socket时(直接关闭应用程序),这时接受端也会收到FD_CLOSE事件。但是这时候再调用recv函数读取socket缓冲区里剩余的数据就会出错,返回-1,这时在socket缓冲区里的剩余数据就全部丢失了。这一点要注意。

7.还有就是直接拔掉网线的情况,收到FD_CLOSE的时机,可以确定,就是在底层的心跳包机制判断连接已经断开之后。这之前网络认为还是联通的,可以读取socket缓冲区里的数据,但是底层判定连接已经断了的情况下,收到了FD_CLOSE,此时再调用recv函数时,会失败,会返回-1.

这些情况都是在做项目时需要考虑的情况,复杂的网络环境可能出现各种情况,需要不断的摸索和总结,以上的结论都是基于windows平台的测试结果。


评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值