S.l.e!ep.¢%

像打了激速一样,以四倍的速度运转,开心的工作
简单、开放、平等的公司文化;尊重个性、自由与个人价值;
posts - 1098, comments - 335, trackbacks - 0, articles - 1
  开发者Cpp博客 :: 首页 :: 新随笔 :: 联系 :: 聚合  :: 管理

谈谈IOCP发送数据时的一些误区及技巧 [转]

Posted on 2009-01-31 06:54 S.l.e!ep.¢% 阅读(3215) 评论(0)  编辑 收藏 引用 所属分类: VC

谈谈IOCP发送数据时的一些误区及技巧  2007-08-24 11:06

分类:默认分类
字号: 大  中  小

 

 

邓立波 深圳,2007-8

作者联系方式 :

email:         libodeng@gmail.com

msn:           libodeng@gmail.com

tel:              13510275799

版权/著作权所有 (C) 2007 邓立波 保留所有权利

警告:未经作者许可,任何人或组织不得转载,公开发布,拷贝,传播本文献的全部或部分

 

误区一,使用 send 函数发送数据

       一些人使用阻塞的 send 函数发送数据,这是绝对应该避免的,一旦某一个连接传输发生拥塞,或者突然中断而没有通知,调用 send 函数的线程将可能被阻塞很长一段时间(可能 10 秒或更长),尤其是当服务器同时处理成千上万个连接时,这种情况可能会频繁出现。

       使用非阻塞的 send 也不适合,数据不一定每次都能完全发送出去,你得使用 select 跟踪这些 socket 的发送状态(一旦可能,发送剩余数据),这失去了 IOCP 的优势。

 

误区二,在多个工作线程的情况下使用 PostQueuedCompletionStatus

       使用 PostQueuedCompletionStatus 向 IOCP 发送一个“写数据 IO 包”,然后由 IOCP 在工作线程里面调用 WSASend 发送数据,这在单个工作线程存在的情况下是安全的,这些“写数据 IO 包”将按它们被投递的顺序取出,并在工作线程中逐一处理。但在多个工作线程存在的情况下,数据仍然按它们投递的顺序取出,但处理不一定有序(即 WSASend 不一定按 PostQueuedCompletionStatus 投递的顺序被调用,iocp是个严格的fifo,线程切换却是随机的),而导致对方接收到的数据可能出现乱序。

 

 

比较好的一种方式是使用调用 WSASend 直接发送数据,注意对同一个连接连续调用多次 WSASend 是安全的,而不需要等到前一个 WSASend 的操作完成,数据将按调用 WSASend 的顺序发送。

在大多数情况下,上面的方式都可以满足要求,但对一个大容量和高并发的服务器,可能还需要对同一个连接限制并发的 IO 次数,以避免冲击可分页内存锁定极限和非分页内存极限,更好的方式是对每个连接仅允许一个 pending send IO ,这可以通过建一个发送缓存队列实现,当 WSASend 未返回操作完成时,后续提交的数据将放置于发送队列,直到 WSASend 完成,然后从发送队列取出一块数据,继续发送。