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

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

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

 

 

邓立波 深圳,2007-8

作者联系方式 :

email:         [email protected]

msn:           [email protected]

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 完成,然后从发送队列取出一块数据,继续发送。

你可能感兴趣的:(谈谈IOCP发送数据时的一些误区及技巧 [转])