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

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

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

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

[html] view plaincopy

  1. //在某个线程里,我们开始向某个客户端疯狂发送这20G的文件了

  2. while(true)

  3. {

  4. char *data=new char[PER_SEND_DATA_LEN];
  5. ::ReadFile(...,data,PER_SEND_DATA_LEN,&len,...);
  6. io_data.wsabuf.buf=data;

  7. io_data.wsabuf.len=len;

  8. ::WSASend(...,&io_data.wsabuf,...);
  9. delete []data;
  10. if(len<PER_SEND_DATA_LEN) break;

  11. }

这样无节操的发送基本上会得到一个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的设计是综合考虑的结果。

时间: 2024-08-09 14:09:46

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

什么地方有卖让人慢性致癌的藥

什么地方有卖让人慢性致癌的藥[订货:186-02559101 联系QQ201558724 林先生]我们做的是长期生意,靠的是老客户长期支持.销售的各种药品药效保证,诚信交易 , 非诚勿扰!梦里花开了又落,你来了又走,渐行渐远的是熟悉的身影.明日,是海鸟和鱼的距离,是天涯与海角的距离.逝水无痕,风轻云淡之际,再回首往事,只见灯火阑珊人影渺茫.[订货:186-02559101 联系QQ201558724 林先生] [什么地方有卖让人慢性致癌的藥]初春的清冷划过心门似冬未去,留在指尖的不是余温而是沉沦

形成人、机器、过程和数据的互联互通

数字信息技术的指数级进步,促成了一个目标的实现,即 “连接一切”.从传统的门户网站.网商.即时通信这种人与人的联接,到工业互联网形式的机器与机器的联接,最终形成人.机器.过程和数据的互联互通.这是一个基于各种传感器信息的数据大爆炸时代,也是一个基于万物互联.云计算.大数据的智能化时代.在这个时代里,我们可以让机器帮助我们感知一切,优化决策,高效执行.

8个让人很舒服的沟通技巧

时间:2015-04-20 11:13 来源:网络 作者:佚名 1.赞美行为而非个人 举例来说,如果对方是厨师,千万不要说:你真是了不起的厨师.他心里知道有更多厨师比他还优秀.但如果你告诉他,你一星期有一半的时间会到他的餐厅吃饭,这就是非常高明的恭维. 2.客套话也要说得恰到好处 客气话是表示你的恭敬和感激,所以要适可而止. 如果对方是经由他人间接听到你的称赞,比你直接告诉本人更多了一份惊喜.相反地,如果是批评对方,千万不要透过第三者告诉当事人,避免加油添醋. 3.面对别人的称赞,说声谢谢就好

从一碗拉面看日本人如何保护饮食隐私

如果你想有一个很好的餐厅体验,包括与工作人员等候互动等等,那么Ichiran拉面可能不是你想去的地方.这间受欢迎的日本连锁店只允许一人就餐,它采取了极端的手段来避免人与人之间的交流,轻松实现安静吃饭的愿望. Manabu Yoshitomi是Ichiran拉面的创始人,他想到这个概念时,还是一名高中生.一次,他亲眼看到自己的女性朋友在吃拉面的时候遮住嘴巴.问过原因之后,Yoshitomi发现她们不愿意被其他人盯着大声吃拉面,这竟是成为她们走入拉面馆的最大障碍.这一信息激发了这位年轻人开了家提供最

思与人

马云说过现在的社会最幸福的生活是工资2-3w的生活.我想相信他,并且用自己的行动来证明这一点.我一个明白这人类含义的人,想自己先明明白白的活着,不想被如今社会的成功所蒙蔽,不想被现今的繁荣所欺骗.我想做到的是自己内心的一份角度去感受这个看似纷杂却是单纯的世界.杀戮,功利,贪欲,一切的一切都是那么渺小与无法被辩驳.因为一旦被剖析那么其中就是一份人类的可爱的缺陷.我们总是以为我们有多么多么的伟大,然而当我们科技在发展,文化在变更的时间长河中,我们改变了什么,什么都没改变.我们虽然增加的寿命,却没有弄

不要对所有人都傻白甜

我一直以善良的形象面向他人.但是,却被那种欺软怕硬的人各种欺负,各种言语挤兑. 所以,我学会了挤兑回去.以前,我从来不知道维护自己的利益.真心,吃大亏后才知道人心多么可怕. 我不得不说,我之前遇到的人们是多么善良,告诉我世界是多么美好,让我一直觉得只要善良就好,不用言语上得理不饶人,不用言语上打击别人.等遇到了那种丑恶嘴脸后,马上发现,原来人心不一定都是好的,有些人就是坏人,需要踩着你才能体现出自己多么高大上.然而,真心是侏儒. You are not a good person!!! 我现在的

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

应该是windows网络编程第二版里面提到过.现在整理一下. 1:在IOCP中投递WSASend返回WSA_IO_PENDING的时候,表示异步投递已经成功,但是稍后发送才会完成.这其中涉及到了三个缓冲区.网卡缓冲区,TCP/IP层缓冲区,程序缓冲区.情况一:调用WSASend发送正确的时候(即立即返回,且没有错误),TCP/IP将数据从程序缓冲区中拷贝到TCP/IP层缓冲区中,然后不锁定该程序缓冲区,由上层程序自己处理.TCP/IP层缓冲区在网络合适的时候,将其数据拷贝到网卡缓冲区,进行真正的

c++ iocp网络模型(转载)

前 言 本系列里完成端口的代码在两年前就已经写好了,但是由于许久没有写东西了,不知该如何提笔,所以这篇文档总是在酝酿之中……酝酿了两年之后,终于决定开始动笔了,但愿还不算晚….. 这篇文档我非常详细并且图文并茂的介绍了关于网络编程模型中完成端口的方方面面的信息,从API的用法到使用的步骤,从完成端口的实现机理到实际使用的注意事项,都有所涉及,并且为了让朋友们更直观的体会完成端口的用法,本文附带了有详尽注释的使用MFC编写的图形界面的示例代码. 我的初衷是希望写一份互联网上能找到的最详尽的关于完成

记录一个蛋疼许久的问题和c语言的一个不太好的地方

在学习的过程中,发现了一个感觉c语言设计中不太好的地方,就是当free内存失败的时候.我造成的错误是因为动态内存越界了,编译器却把free()函数报错,简直感觉有些不能忍受.应该在设计的时候第一时间将问题暴露在那个越界了的地方,否则会让人莫名其妙,难以找到错误,为此浪费时间和精力. 另一个是关于txt文件的读取问题,一我这次学了个乖,每次操作的时候,务必记住了,当前的txt文件是什么编码,否则出现了错误就让人有些摸不着头脑,完全影响了学习的心情.以后注意不再犯了.仅作一个记录.