IOCP的工做线程的个数通常设置为processors *2+2,这是综合考虑了工做线程多是等待/挂起/正在执行的状态。若是你测试出更好的结果,以你的为标准。算法
IOCP的工做线程由系统调度和优化,不要去干预线程的调度,除非你自信能超越系统的调度。编程
在遇到奇怪的问题时,能够尝试减小IOCP工做线程数量,来定位问题所在。网络
应用层在处理收到的数据时,尽快将数据处理掉或是拷贝一份,避免阻塞IOCP工做线程。app
在投递I/O和收到该I/O完成通知(无论成功失败)期间,注意保存好Overlapped I/O结构,以避免出现奇怪的内存问题。异步
在投递I/O时,若是返回WSA_IO_PENDING,意味着投递操做成功,可是稍后才会处理完成。通常说来,投递发送或接收IO请求多是下面三种结果, 以调用WSASend为例:
I.若是操做错误码是ERROR_SUCCESS,系统将程序缓冲区拷贝到内核缓冲区(也就是TCP/IP栈缓冲区)中,而后在网络适当的时候(好比符合Nagle算法的发送条件),将数据拷贝到网卡缓冲区,进行真正的发送;
II.若是操做错误码是WSA_IO_PENDING,意味着此时内核缓冲区空间不够,系统将锁定程序缓冲区锁定到非分页内存中,直到内核缓冲区有足够的空间来将数据拷贝走;
III.若是操做结果是其余错误码,根据具体缘由,能够选择释放socket对应的资源。(该条目参考《Windows网络编程第2版》)socket
尽可能使I/O缓冲区的大小是系统页面大小的倍数(32位是4k),这样避免系统在拷贝程序缓冲区在不足一倍数时而占用整个页面。测试
尽可能投递大型I/O操做,也就是每次发送较大的数据包,而不是屡次发送一些小的数据包,且每次发送数据都固定大小。优化
使用AcceptEx异步接收的链接,若是要获取本地/对端的地址,有两种方式:
I.使用扩展API:GetAcceptExSockaddrs,能够同时获取本地/对端地址,须要I/O结构的支持;
II.使用标准API:getsockname/getpeername,因为对端socket还没有与监听socket彻底绑定,须要先设置SO_UPDATE_ACCEPT_CONTEXT 选项,而后才能够正常获取到。(适用于winxp之后的版本)spa
在关闭Socket时,注意处理未决的IO请求,这些请求以失败的结果(GetQueuedCompletionStatus失败)返回。线程
常见错误码:ERROR_NETNAME_DELETED(64):对端关闭socketERROR_OPERATION_ABORTED(995):本端socket被关闭,操做取消