IOCP 的一些问题总结

  1. IOCP的工作线程的个数一般设置为processors *2+2,这是综合考虑了工作线程可能是等待/挂起/正在执行的状态。如果你测试出更好的结果,以你的为标准。

  2. IOCP的工作线程由系统调度和优化,不要去干预线程的调度,除非你自信能超越系统的调度。

  3. 在遇到奇怪的问题时,可以尝试减少IOCP工作线程数量,来定位问题所在。

  4. 应用层在处理收到的数据时,尽快将数据处理掉或是拷贝一份,避免阻塞IOCP工作线程。

  5. 在投递I/O和收到该I/O完成通知(不管成功失败)期间,注意保存好Overlapped I/O结构,以免出现奇怪的内存问题。

  6. 在投递I/O时,如果返回WSA_IO_PENDING,意味着投递操作成功,但是稍后才会处理完成。一般说来,投递发送或接收IO请求可能是下面三种结果, 以调用WSASend为例:
    I.如果操作错误码是ERROR_SUCCESS,系统将程序缓冲区拷贝到内核缓冲区(也就是TCP/IP栈缓冲区)中,然后在网络适当的时候(比如符合Nagle算法的发送条件),将数据拷贝到网卡缓冲区,进行真正的发送;
    II.如果操作错误码是WSA_IO_PENDING,意味着此时内核缓冲区空间不够,系统将锁定程序缓冲区锁定到非分页内存中,直到内核缓冲区有足够的空间来将数据拷贝走;
    III.如果操作结果是其他错误码,根据具体原因,可以选择释放socket对应的资源。(该条目参考《Windows网络编程第2版》)

  7. 尽量使I/O缓冲区的大小是系统页面大小的倍数(32位是4k),这样避免系统在拷贝程序缓冲区在不足一倍数时而占用整个页面。

  8. 尽量投递大型I/O操作,也就是每次发送较大的数据包,而不是多次发送一些小的数据包,且每次发送数据都固定大小。

  9. 使用AcceptEx异步接收的连接,如果要获取本地/对端的地址,有两种方式:
    I.使用扩展API:GetAcceptExSockaddrs,可以同时获取本地/对端地址,需要I/O结构的支持;
    II.使用标准API:getsockname/getpeername,由于对端socket尚未与监听socket完全绑定,需要先设置SO_UPDATE_ACCEPT_CONTEXT 选项,然后才可以正常获取到。(适用于winxp以后的版本)

  10. 在关闭Socket时,注意处理未决的IO请求,这些请求以失败的结果(GetQueuedCompletionStatus失败)返回。

  11. 常见错误码:
    ERROR_NETNAME_DELETED(64):对端关闭socket
    ERROR_OPERATION_ABORTED(995):本端socket被关闭,操作取消


你可能感兴趣的:(IOCP 的一些问题总结)