在WinSock的IOCP模式中,调用WSASend/WSARecv/WSASendTo/WSARecvFrom等函数发送接受数据。调用WSAxxx函数发送或者接受数据时,如果函数返回了0,表示操作已经立即完成了。但是一般不会在这时进行完成操作的处理,因为Socket已经和完成端口绑定,某个调用GetQueuedCompletionStatus/GetQueuedCompletionStatusEx函数的线程一定会得到这个完成通知;此时处理了,下次得到通知时还需要把它和其它正常的通知区分开来,是自找麻烦。
对于某些UDP服务器程序,比如DNS服务器,处理的都是比较小的报文,大多数情况下操作都是可以立即完成的,没有必要下次得到完成端口的通知时再处理。有没有办法不让完成端口通知那些立即完成的操作呢?正好有这么一个函数可以满足需要:SetFileCompletionNotificationModes。SetFileCompletionNotificationModes函数可以在一个句柄上设置一个标记:FILE_SKIP_COMPLETION_PORT_ON_SUCCESS,如果一个句柄设置了这个标记,在操作立即完成时,IO管理器就不会在句柄关联的完成端口上添加完成通知。
可以这个函数只有在Vista之后才支持。SetFileCompletionNotificationModes内部调用了ZwSetInformationFile,指定的第五个参数FILE_INFORMATION_CLASS是41(FileIoCompletionNotificationInformation),而FileIoCompletionNotificationInformation这个class在Windows 2000/XP/2003是不支持的。