关于IOCP,某些地方就是不让人彻底舒服(WSASend重叠post数据)

简介: 开门见山,直接就事论事。   假如有这么一个基于IOCP模型的Server,这个Server提供的所有服务中有这么一种服务……文件下载,我们再假设Server端存有一个20G的文件,客户端这时发送一个请求到服务端来,客户端要求下载这个20G的文件,由此可能引发一系列让人头疼的问题(不谈Trans...

开门见山,直接就事论事。

 

假如有这么一个基于IOCP模型的Server,这个Server提供的所有服务中有这么一种服务……文件下载,我们再假设Server端存有一个20G的文件,客户端这时发送一个请求到服务端来,客户端要求下载这个20G的文件,由此可能引发一系列让人头疼的问题(不谈TransmitFile,我们谈WSASend)

 

先给出一段伪代码,这段代码肯定是有问题的,如下:

[html]  view plain copy
  1. //在某个线程里,我们开始向某个客户端疯狂发送这20G的文件了  
  2. while(true)  
  3. {  
  4.     char *data=new char[PER_SEND_DATA_LEN];  
  5.   
  6.     ::ReadFile(...,data,PER_SEND_DATA_LEN,&len,...);  
  7.   
  8.     io_data.wsabuf.buf=data;  
  9.     io_data.wsabuf.len=len;  
  10.     ::WSASend(...,&io_data.wsabuf,...);  
  11.   
  12.     delete []data;  
  13.       
  14.     if(len<PER_SEND_DATA_LEN) break;  
  15. }  

这样无节操的发送基本上会得到一个WSAENOBUFS(缓冲区不足)错误,这个不是什么大问题,不会影响到IOCP底层模块的设计,值得注意的是下面一个问题——数据发送不完全

 

接着上面的例子继续思考下去。

假如其中一个WSASend投递长度为PER_SEND_DATA_LEN的数据,而GetQueuedCompletionStatus(...,&BytesTransferred,...)返回结果却表明这次发送没有进行完全,BytesTransferred<PER_SEND_DATA_LEN,而后续的WSASend函数正源源不断地投递新的请求,即使我们在Get函数返回后,再次投递WSASend请求补发剩余数据,也无法保证这样的补发可以赶在其他WSASend的前面。

 

如果以上推测成立的话,那么数据将不可避免的出现乱序。

 

当然,这只是一种担心,实际上到目前为止,本人还没有遇到过这种情况,个人认为:这种情况应该不会发生,一定是哪些地方还没有搞透彻,否则重叠的意义何在?不过,网上担心这种情况的人也不少,以下是提出这些问题的链接(不保证都是原创):

http://blog.csdn.net/skiing_886/article/details/8044186

http://bbs.eyuyan.com/read.php?tid=306324

 

上面两个链接中,其中一个是篇博客,博客中明言WSASend带重叠结构投递请求时,不会出现数据发送不完全的情况,本人比较容易相信别人,于是我就信了。就算那篇博客说错了,本人也还是觉得数据乱序的情况不会发生。

 

下面,本人想就这个问题,结合IOCP的完成队列说一些自己的猜想(完全是猜想,假设WSASend所投递的数据有可能发送不完全)。

首先,IOCP维护着一个的队列,这个队列没有好妖魔化的,就是一个先进先出的数据结构,效率很高就是了。问题是,是不是我们每次调用WSASend都将导致一次入列,而每次GetQueuedCompletionStatus函数返回都会导致一次出列呢?

 

结合上面的那个下载文件的例子,细细一想,如果每次GetQueuedCompletionStatus返回都要出列一次数据包的话,那一旦出现数据发送不完全的情况,即使我们再次调用WSASend补发,那也只能将数据附加到完成队列的头部,乱序是必然的。

 

但是,换个思维,这种问题连我都能想到,微软那么多高智商人才难道都是吃干饭的吗?

 

所以,我认为,当数据发送不完全的时候,GetQueuedCompletionStatus应该是不会出列数据的,而可能是占着茅坑不拉屎,等待WSASend再次补发未完成的数据发送,而这个WSASend肯定不会导致数据数据重新入列,而只是给一个继续发送的信号。

 

如果是我的,我肯定会这样设计,否则,那就只能采取保险的做法,WSASend不重叠投递,一次投递之后需要等待Get函数返回再决定是要投递一个补发的WSASend请求还是投递下一个完整数据包的WSASend请求。这种做法虽然保险,但这突出了IOCP的巨大缺陷,正如我前面所说的,重叠的意义何在?WSASend还有必要带着个OVERLLAPED结构吗?

 

所以,我认为,这种情况的数据乱序不可能发生,不用担心,嗯,不担心……

 

说到最后,再顺便提一下STL。STL的出列操作是Pop,它是不带任何返回值的出列,要想知道出列了什么数据必须在Pop之前调用front方法。有人强烈鄙视这种设计,认为这种设计极其别扭。要知道,STL的设计者必然是高手,设计成这样自然有理由,队列这种东西,要想通用的话,最好还是要把‘看’和‘取’分开,STL的设计是综合考虑的结果。

目录
相关文章
|
并行计算 算法 搜索推荐
简单学习一下AES算法:GCM、ECB、CFB、OFB等
简单学习一下AES算法:GCM、ECB、CFB、OFB等
3538 0
|
算法 安全 编译器
理解和记忆std::atomic
理解和记忆std::atomic
306 0
|
C语言 容器
【qt】动态属性(下)
【qt】动态属性(下)
274 1
|
机器人 定位技术 计算机视觉
Qt实用技巧:使用Qt加载超大图片的耗时测试
Qt实用技巧:使用Qt加载超大图片的耗时测试
Qt实用技巧:使用Qt加载超大图片的耗时测试
|
Oracle 关系型数据库 数据库
|
数据采集 安全 JavaScript
​HTML代码混淆技术:原理、应用和实现方法详解
​HTML代码混淆技术:原理、应用和实现方法详解
697 0
|
网络协议 网络安全 Windows
IOCP详解
IOCP(I/O Completion Port,I/O完成端口)是性能最好的一种I/O模型。它是应用程序使用线程池处理异步I/O请求的一种机制。
13902 0
|
API 开发工具 iOS开发
|
10月前
|
Windows
缺少文件X3DAudio1_7.dll问题解决!找不到x3daudio1_7.dll怎么解决?
当电脑提示“找不到X3DAudio1_7.dll”或“X3DAudio1_7.dll缺失”时,可能是DirectX版本不兼容所致。该DLL文件负责游戏音效传输,缺失会导致游戏声音异常。解决方法包括:下载缺失的DLL文件、使用DLL修复工具(如DirectxRepair一键修复)、安装游戏常用运行库合集。部分安装问题可通过关闭杀毒软件、使用管理员账户操作解决。
7115 0
|
JSON 安全 JavaScript
利用Webhook绕过支付请求
在深入了解漏洞奖励计划中的安全漏洞时,我们往往需要寻找一些用户不可见的功能下手。支付Webhook就是一种典型例子,像Stripe或Braintree这样的支付服务提供商都会使用这种技术来将用户的订购细节告知网站。重要的是,用户根本不会跟这些Webhook节点进行交互,所有的通信都是在支付提供商和服务器之间完成的。这也就意味着,很多漏洞Hunter可能从来都不会想到要去测试Webhook功能,这也就会错过很多潜在的高危漏洞。