Since the WinSock DLL itself is no longer supplied by each individual stack vendor, it is no longer possible for a stack vendor to offer extended functionality by just adding entry points to the WinSock DLL. To overcome this limitation, WinSock 2 takes advantage of the new WSAIoctl() function to accommodate service providers who wish to offer provider-specific functionality extensions. This mechanism presupposes, of course, that an application is aware of a particular extension and understands both the semantics and syntax involved. Such information would typically be supplied by the service provider vendor.
In order to invoke an extension function, the application must first ask for a pointer to the desired function. This is done via the WSAIoctl() function using the SIO_GET_EXTENSION_FUNCTION_POINTER command code. The input buffer to the WSAIoctl() function contains an identifier for the desired extension function and the output buffer will contain the function pointer itself. The application can then invoke the extension function directly without passing through the WinSock 2 DLL.
The identifiers assigned to extension functions are globally unique identifiers (GUIDs) that are allocated by service provider vendors.. Vendors who create extension functions are urged to publish full details about the function including the syntax of the function prototype. This makes it possible for common and/or popular extension functions to be offered by more than one service provider vendor. An application can obtain the function pointer and use the function without needing to know anything about the particular service provider that implements the function.
19 Debug and Trace Facilities
When the developer of a WinSock 2 application encounters a WinSock-related bug there is a need to isolate the bug to either (1) the application, (2) the WinSock 2 DLL (or one of it’s 1.1 compatibility “shim” DLLs), or (3) the service provider. WinSock 2 addresses this need through a specially instrumented version of the WinSock 2 DLL and a separate debug/trace DLL. This combination allows all procedure calls across the WinSock 2 API or SPI to be monitored, and to some extent controlled.
Developers can use this mechanism to trace procedure calls, procedure returns, parameter values, and return values. Parameter values and return values can be altered on procedure-call or procedure-return. If desired, a procedure-call can even be prevented or redirected. With access to this level of information and control, it should be easy for a developer to isolate any problem to the application, WinSock 2 DLL or service provider.
The WinSock 2 SDK includes the instrumented WinSock 2 DLL, a sample debug/trace DLL and a document containing a detailed description of the above two components. The sample debug/trace DLL is provided in both source and object form. Developers are free to use the source to develop versions of the debug/trace DLL that meet their special needs.
20 Protocol Independent Name Resolution
WinSock 2 includes provisions for standardizing the way applications access and use the various network name resolution services. WinSock 2 applications will not need to be cognizant of the widely differing interfaces associated with name services such as DNS, NIS, X.500, SAP, etc. An introduction to this topic and the details of the APIs are currently located in section 128 Protocol-Independent Name Resolution
21 Overlapped I/O and Event Objects
WinSock 2 introduces overlapped I/O and requires that all transport providers support this capability. Overlapped I/O can be performed only on sockets that were created via the WSASocket() function with the WSA_FLAG_OVERLAPPED flag set (or created via the socket() function), and follows the model established in Win32.
Note that creating a socket with the overlapped attribute has no impact on whether a socket is currently in the blocking or non-blocking mode. Sockets created with the overlapped attribute may be used to perform overlapped I/O, and doing so does not change the blocking mode of a socket. Since overlapped I/O operations do not block, the blocking mode of a socket is irrelevant for these operations.
For receiving, applications use WSARecv() or WSARecvFrom() to supply buffers into which data is to be received. If one or more buffers are posted prior to the time when data has been received by the network, it is possible that data will be placed into the user’s buffers immediately as it arrives and thereby avoid the copy operation that would otherwise occur at the time the recv() or recvfrom() function is invoked. If data is already present when receive buffers are posted, it is copied immediately into the user’s buffers. If data arrives when no receive buffers have been posted by the application, the network resorts to the familiar synchronous style of operation where the incoming data is buffered internally until such time as the application issues a receive call and thereby supplies a buffer into which the data may be copied. An exception to this would be if the application used setsockopt() to set the size of the receive buffer to zero. In this instance, reliable protocols would only allow data to be received when application buffers had been posted, and data on unreliable protocols would be lost.
On the sending side, applications use WSASend() or WSASendTo() to supply pointers to filled buffers and then agree to not disturb the buffers in any way until such time as the network has consumed the buffer's contents.
Overlapped send and receive calls return immediately. A return value of zero indicates that the I/O operation completed immediately and that the corresponding completion indication has already occurred. That is, the associated event object has been signaled, or a completion routine has been queued and will be executed when the calling thread gets into the alterable wait state. A return value of SOCKET_ERROR coupled with an error code of WSA_IO_PENDING indicates that the overlapped operation has been successfully initiated and that a subsequent indication will be provided when send buffers have been consumed or when a receive operation has been completed. However, for byte stream style sockets, the completion indication occurs whenever the incoming data is exhausted, regardless of whether the buffers are fully filled. Any other error code indicates that the overlapped operation was not successfully initiated and that no completion indication will be forthcoming.
Both send and receive operations can be overlapped. The receive functions may be invoked multiple times to post receive buffers in preparation for incoming data, and the send functions may be invoked multiple times to queue up multiple buffers to be sent. Note that while the application can rely upon a series of overlapped send buffers being sent in the order supplied, the corresponding completion indications may occur in a different order. Likewise, on the receiving side, buffers will be filled in the order they are supplied but the completion indications may occur in a different order.
There is no way to cancel individual overlapped operations pending on a given socket, however, the closesocket() function can be called to close the socket and eventually discontinue all pending operations.
The deferred completion feature of overlapped I/O is also available for WSAIoctl() which is an enhanced version of ioctlsocket().
22 Event Objects
Introducing overlapped I/O requires a mechanism for applications to unambiguously associate send and receive requests with their subsequent completion indications. In WinSock 2 this may be accomplished via event objects which are modeled after Win32 events. WinSock event objects are fairly simple constructs which can be created and closed, set and cleared, waited upon and polled. Their prime usefulness comes from the ability of an application to block and wait until one or more event objects become set.
Applications use WSACreateEvent() to obtain an event object handle which may then be supplied as a required parameter to the overlapped versions of send and receive calls (WSASend(), WSASendTo(), WSARecv(), WSARecvFrom()). The event object, which is cleared when first created, is set by the transport providers when the associated overlapped I/O operation has completed (either successfully or with errors). Each event object created by WSACreateEvent() should have a matching WSACloseEvent() to destroy it.
Event objects are also used in WSAEventSelect() to associate one or more FD_XXX network events with an event object. This is described in section 2.7. Asynchronous Notification Using Event Objects.
In 32-bit environments, event object related functions, including WSACreateEvent(), WSACloseEvent(), WSASetEvent(), WSAResetEvent(), and WSAWaitForMultipleEvents()are directly mapped to the corresponding native Win32 functions, i.e. the same function name without the WSA prefix.
23 Receiving Completion Indications
In order to provide applications with appropriate levels of flexibility, several options are available for receiving completion indications. These include: waiting on (i.e. blocking on) event objects, polling event objects, and socket I/O completion routines.
24 Blocking and Waiting for Completion Indication
Applications may choose to block while waiting for one or more event objects to become set using WSAWaitForMultipleEvents(). Since WinSock 2 event objects are implemented as Win32 events, the native Win32 function WaitForMultipleObjects() may also be used for this purpose. This is especially useful if the thread needs to wait on both socket and non-socket events.
25 Polling for Completion Indication
Applications that prefer not to block may use WSAGetOverlappedResult() to poll for the completion status associated with any particular event object. This function indicates whether or not the overlapped operation has completed, and, if completed, arranges for WSAGetLastError() to retrieve the error status of the overlapped operation.
26 Using socket I/O completion routines
The functions used to initiate overlapped I/O (WSASend(), WSASendTo(), WSARecv(), WSARecvFrom()) all take lpCompletionRoutine as an optional input parameter. This is a pointer to an application-specified function that will be called after a successfully initiated overlapped I/O operation has completed (successfully or otherwise). The completion routine follows the same rules as stipulated for Win32 file I/O completion routines. The completion routine will not be invoked until the thread is in an alertable wait state such as can occur when the function WSAWaitForMultipleEvents() is invoked with the fAlertable flag set. Note that an application that uses the completion routine option for a particular overlapped I/O request may not use the “wait” option of WSAGetOverlappedResult() for that same overlapped I/O request.
Transports allow an application to invoke send and receive operations from within the context of the socket I/O completion routine, and guarantee that, for a given socket, I/O completion routines will not be nested. This permits time-sensitive data transmissions to occur entirely within a preemptive context.
27 Summary of overlapped completion indication mechanisms
The particular overlapped I/O completion indication to be used for a given overlapped operation is determined by whether or not the application supplies a pointer to a completion function, whether or not a WSAOVERLAPPED structure is referenced, and the value of the hEvent field within the WSAOVERLAPPED structure (if supplied). The following table summarizes the completion semantics for an overlapped socket, showing the various combination of lpOverlapped, hEvent, and lpCompletionRoutine:
lpOverlapped
|
hEvent
|
lpCompletionRoutine
|
Completion Indication
|
NULL
|
not applicable
|
ignored
|
Operation completes synchronously, i.e. it behaves as if it were a non-overlapped socket.
|
!NULL
|
NULL
|
NULL
|
Operation completes overlapped, but there is no WinSock 2 supported completion mechanism. The completion port mechanism (if supported) may be used in this case, otherwise there will be no completion notification.
|
!NULL
|
!NULL
|
NULL
|
Operation completes overlapped, notification by signaling event object.
|
!NULL
|
ignored
|
!NULL
|
Operation completes overlapped, notification by scheduling completion routine.
|
28 WSAOVERLAPPED Details
The WSAOVERLAPPED structure provides a communication medium between the initiation of an overlapped I/O operation and its subsequent completion. The WSAOVERLAPPED structure is designed to be compatible with the Win32 OVERLAPPED structure:
typedef struct _WSAOVERLAPPED {
DWORD Internal; // reserved
DWORD InternalHigh; // reserved
DWORD Offset; // reserved
DWORD OffsetHigh; // reserved
WSAEVENT hEvent;
} WSAOVERLAPPED, LPWSAOVERLAPPED;
Internal This reserved field is used internally by the entity that implements overlapped I/O. For service providers that create sockets as installable file system (IFS) handles, this field is used by the underlying operating system. Other service providers (non-IFS providers) are free to use this field as necessary.
InternalHigh This reserved field is used internally by the entity that implements overlapped I/O. For service providers that create sockets as IFS handles, this field is used by the underlying operating system. Non-IFS providers are free to use this field as necessary.
Offset This field is reserved for service providers to use.
OffsetHigh This field is reserved for service providers to use.
hEvent If an overlapped I/O operation is issued without an I/O completion routine (lpCompletionRoutine is NULL), then this field should either contain a valid handle to a WSAEVENT object or be NULL. If lpCompletionRoutine is non-NULL then applications are free to use this field as necessary. An application that uses a non-NULL lpCompletionRoutine for a particular overlapped I/O request may not use the “wait” option of WSAGetOverlappedResult() for that same overlapped I/O request.
Share with your friends: |