IOCP中在WSASend以及WSARecv的时候出现WSA_IO_PENDING情况的说明

转载 2015年07月10日 13:50:37
原文出处

网络编程 2010-08-11 11:05:53 阅读293 评论0   字号:大中小 订阅 
应该是windows网络编程第二版里面提到过。现在整理一下。 
1:在IOCP中投递WSASend返回WSA_IO_PENDING的时候,表示异步投递已经成功,但是稍后发送才会完成。这其中涉及到了三个缓冲区。 
网卡缓冲区,TCP/IP层缓冲区,程序缓冲区。 
情况一:调用WSASend发送正确的时候(即立即返回,且没有错误),TCP/IP将数据从程序缓冲区中拷贝到TCP/IP层缓冲区中,然后不锁定该程序缓冲区,由上层程序自己处理。TCP/IP层缓冲区在网络合适的时候,将其数据拷贝到网卡缓冲区,进行真正的发送。 
情况二:调用WSASend发送错误,但是错误码是WSA_IO_PENDING的时候,表示此时TCP/IP层缓冲区已满,暂时没有剩余的空间将程序缓冲区的数据拷贝出来,这时系统将锁定用户的程序缓冲区,按照书上说的WSASend指定的缓冲区将会被锁定到系统的非分页内存中。直到TCP/IP层缓冲区有空余的地方来接受拷贝我们的程序缓冲区数据才拷贝走,并将给IOCP一个完成消息。 
情况三:调用WSASend发送错误,但是错误码不是WSA_IO_PENDING,此时应该是发送错误,应该释放该SOCKET对应的所有资源。 
2:在IOCP中投递WSARecv的时候,情况相似。 
情况一:调用WSARecv正确,TCP/IP将数据从TCP/IP层缓冲区拷贝到缓冲区,然后由我们的程序自行处理了。清除TCP/IP层缓冲区数据。 
情况二:调用WSARecv错误,但是返回值是WSA_IO_PENDING,此时是因为TCP/IP层缓冲区中没有数据可取,系统将会锁定我们投递的WSARecv的buffer,直到TCP/IP层缓冲区中有新的数据到来。 
情况三:调用WSARecv错误,错误值不是WSA_IO_PENDING,此时是接收出错,应该释放该SOCKET对应的所有资源。 
在以上情况中有几个非常要注意的事情: 
系统锁定非分页内存的时候,最小的锁定大小是4K(当然,这个取决于您系统的设置,也可以设置小一些,在注册表里面可以改,当然我想这些数值微软应该比我们更知道什么合适了),所以当我们投递了很多WSARecv或者WSASend的时候,不管我们投递的Buffer有多大(0除外),系统在出现IO_PENGDING的时候,都会锁定我们4K的内存。这也就是经常有开发者出现WSANOBUF的情况原因了。 
我们在解决这个问题的时候,要针对WSASend和WSARecv做处理 
1:投递WSARecv的时候,可以采用一个巧妙的设计,先投递0大小Buf的WSARecv,如果返回,表示有数据可以接收,我们开启真正的recv将数据从TCP/IP层缓冲区取出来,直到WSA_IO_PENGDING. 
2:对投递的WSARecv以及WSASend进行计数统计,如果超过了我们预定义的值,就不进行WSASend或者WSARecv投递了。 
3:现在我们应该就可以明白为什么WSASend会返回小于我们投递的buffer空间数据值了,是因为TCP/IP层缓冲区小于我们要发送的缓冲区,TCP/IP只会拷贝他剩余可被Copy的缓冲区大小的数据走,然后给我们的WSASend的已发送缓冲区设置为移走的大小,下一次投递的时候,如果TCP/IP层还未被发送,将返回WSA_IO_PENGDING。 

4:在很多地方有提到,可以关闭TCP/IP层缓冲区,可以提高一些效率和性能,这个从上面的分析来看,有这个可能,要实际的网络情况去实际分析了。

==================================================

 所谓的锁定就是 内核征用了你的缓冲区
在I/0操作返回前,这块内存你不要做其它事(此时,系统内核也在用这块内存)

如果要同时做 收,发操作
就要开辟两个缓冲区 ReadBuf,WriteBuf
这两个缓冲区彼此独立
==================================================

相关文章推荐

iocp(完成端口)采用WSARecv WSASend处理数据,WSASend群发(广播)消息

最近在耍iocp,也在网上看了不少例子,但却基本没看到使用WSASend群发的例子 最多只是使用WSASend将数据回传,而这个功能相对比较简单,只要学会使用WSARecv 回传则比较容易实现,而...

重叠I/O完成例程模型如何同时投递WSARecv和WSASend

参考自这篇文章: http://www.winsocketdotnetworkprogramming.com/winsock2programming/winsock2advancediomethod...

关于WSARECV与WSASEND,SOCKET_ERROR关闭997异常的问题

原文链接: http://www.xixis.net/doserver.net//read.php/2063.htm 最近写一个IOCP的服务器程序, 在WSARECV出现SOCKET...

IOCP 使用WSASend群发消息

  • 2015-04-28 15:12
  • 3.61MB
  • 下载

IOCP中多次投递WSASend

关于IOCP中是否可以对同一socket连续投递的疑问已经很久了,主要的疑问在wsaSend是否可以保证数据的完整发送,是否会出现部分发送成功的情况?       网上大多数的建议都是WSASEND...
  • zy100
  • zy100
  • 2011-02-24 15:15
  • 11427

IOCP中多次投递WSASend

关于IOCP中是否可以对同一socket连续投递的疑问已经很久了,主要的疑问在wsaSend是否可以保证数据的完整发送,是否会出现部分发送成功的情况?       网上大多数的建议都是WSASEND...

当一个界面有多个ViewPager的时候,如果出现某一个不显示的情况

这个问题第一次出现,完全没有头绪,后来看了别人的说明之后实验了一下,确实是这种问题。 转自:http://blog.csdn.net/hknock/article/details/50629754多...

Android SDK Manager SDK Manager.exe下载全部平台时更新包的时候出现无法下载的情况

转自:http://blog.csdn.net/cyj5366/article/details/9766993 Done loading packages. Fetching https:...

tomcat启动时出现异常Exception loading sessions from persistent storage分析: session未超时的情况下,服务器关闭的时候会被序列化为工程名\

Exception loading sessions from persistent storage  Java.io.EOFException  at java.io.ObjectInputSt...

thinkphp框架实例化模型的时候出现了“Undefined index: validate”或者“Undefined index: auto”情况?

最近用tp 3.2.3版本框架实例化模型的时候出现了一个很奇怪的警告,“Undefined index: validate”或者“Undefined index: auto”? 记得我用以前版本的3...
内容举报
返回顶部
收藏助手
不良信息举报
您举报文章:深度学习:神经网络中的前向传播和反向传播算法推导
举报原因:
原因补充:

(最多只允许输入30个字)