This article explains the difference between a socket's overlapped I/Oattribute and the socket's blocking or nonblocking mode.
When a socket is created, by default it is a blocking socket. You can usethe FIONBIO command in the ioctlsocket API call, WSAEventSelect, orWSAAysncSelect to change the socket mode from blocking to nonblocking. Ifa Winsock call cannot complete immediately, the call fails andWSAGetLastError returns a WSAEWOULDBLOCK error if it's a nonblockingsocket, or the call blocks until the operation completes if it's a blockingsocket.
The socket overlapped I/O attribute is different from the socket's blockingor nonblocking mode. Although the current Winsock implementation requiresoverlapped I/O attribute for nonblocking socket mode, they areconceptually independent and their programming model is different too. Tocreate a socket with the overlapped I/O attribute, you can either use thesocket API or the WSASocket API with the WSA_FLAG_OVERLAPPED flag set. Ifan overlapped I/O operation can not complete immediately, the call failsand WSAGetLastError or GetLastError return WSA_IO_PENDING orERROR_IO_PENDING, which is actually the same define as WSA_IO_PENDING. Foradditional information, please see the following article in theMicrosoft Knowledge Base:
INFO: WSA_FLAG_OVERLAPPED Is Needed For Non-Blocking Sockets
Please note that once a socket is created, there is no way to change thesocket overlapped attribute. However, you can call the setsockopt API withSO_OPENTYPE option on any socket handles including an INVALID_SOCKET tochange the overlapped attributes for all successive socket calls in thesame thread. The default SO_OPENTYPE option value is 0, which sets theoverlapped attribute. All nonzero option values make the socketsynchronous and make it so that you cannot use a completion function.
By setting a socket's overlapped I/O attribute it doesn't mean that thesocket will perform an overlapped I/O operation. For example, if youspecify NULL for both the completion function and the overlapped structurein WSARecv and WSASend, or you simply call recv or send functions, theywill complete in a blocking fashion. To make sure the I/O is performed inan overlapped fashion you need to provide an overlapped structure in yourI/O function, depending on the function you use.
In Winsock 1, you create an overlapped socket using the socket API, and useWin32 file I/O API ReadFile, ReadFileEx, WriteFile, WriteFileEx to performoverlapped I/O on the socket handle. In Winsock 2, you create an overlappedsocket using WSASocket with the WSA_FLAG_OVERLAPPED flag, or simply usingthe socket API. You can use the above Win32 file I/O APIs or Winsock 2WSASend, WSASendTo, WSARecv, and WSARecvFrom to initiate an overlapped I/Ooperation.
If you use the SO_RCVBUF and SO_SNDBUF option to set zero TCP stack receiveand send buffer, you basically instruct the TCP stack to directly performI/O using the buffer provided in your I/O call. Therefore, in addition tothe nonblocking advantage of the overlapped socket I/O, the otheradvantage is better performance because you save a buffer copy between theTCP stack buffer and the user buffer for each I/O call. But you have tomake sure you don't access the user buffer once it's submitted foroverlapped operation and before the overlapped operation completes.
To determine whether the overlapped I/O operation is completed, you can useone of the following options:
- You can provide an event handle in an overlapped structure used in the I/O call and wait on the event handle to signal.
- Use GetOverlappedResult or WSAGetOverlappedResult to poll the status of the overlapped I/O operation. On Windows NT, you can specify NULL as the event handle in the overlapped structure. However, on Windows 95 the overlapped structure needs to contain a manual reset event handle. WSAGetOverlappedResult on Windows 98 and Windows Millennium Edition (ME) is modified such that it will behave like Windows NT and can also poll the completion status with a NULL event handle in the overlapped structure.
- Use ReadFileEx, WriteFileEx, WSARecv, WSARecvFrom, WSASend, or WSASendTo and choose to provide a completion function to be called when the overlapped I/O operation has completed. If you use the completion function approach, at some point after you have issued the overlapped I/O operation you need to issue a Win32 wait function or a WSA version of wait function to wait on a nonsignaled handle to put your current thread into an alertable wait state. When the overlapped I/O operation completes, your completion function is called, your wait function is going to return WAIT_IO_COMPLETION, and your alertable wait thread wakes up.
- Use GetQueuedCompletionStatus and associate a socket, along with the overlapped I/O attribute set, with a Windows NT I/O Completion Port(IOCP).
With IOCP, you don't need to supply a completion function, wait on an event handle to signal, or poll the status of the overlapped operation. Once you create the IOCP and add your overlapped socket handle to the IOCP, you can start the overlapped operation by using any of the I/O APIs mentioned above (except recv, recvfrom, send, or sendto). You will have your worker thread block on GetQueuedCompletionStatus API waiting for an I/O completion packet. When an overlapped I/O completes, an I/O completion packet arrives at the IOCP and GetQueuedCompletionStatus returns.
IOCP is the Windows NT Operating System support for writing a scalable, high throughput server using very simple threading and blocking code on overlapped I/O operations. Thus there can be a significant performance advantage of using overlapped socket I/O with Windows NT IOCPs.
Blocking and nonblocking mode
When a socket is created, by default it is a blocking socket. Underblocking mode socket I/O operations, connect and accept operations allblock until the operation in question is completed. To change the socketoperation mode from blocking mode to nonblocking mode, you can either useWSAAsyncSelect, WSAEventSelect, or the FIONBIO command in the ioctlsocketAPI call.
WSAAsyncSelect maps socket notifications to Windows messages and is thebest model for a single threaded GUI application.
WSAEventSelect uses WSAEnumNetworkEvents to determine the nature of thesocket notification on the signaling event and maps socket notifications bysignaling an event. This is a useful model for non-GUI applications thatlack a message pump, such as a Windows NT service application.
The FIONBIO command in the ioctlsocket API call puts the socket into nonblocking mode as well. But you need to poll the status of the socket byusing the select API.
Update: Setting SO_RCVBUF to zero with overlapped recv is not necessary for Windows 2000, which can directly copy the data to application's recv buffer. Setting SO_SNDBUF to zero with overlapped send on Windows 2000 still has the same benefit of saving one memory copy as on Windows NT 4.0. It is also important that the application issues several outstanding overlapped send's or recv's if the application sets the corresponding stack buffer to 0.