Windows* Sockets 2 Application Programming Interface An Interface for Transparent Network Programming Under Microsoft Windowstm revision 2 August 7, 1997


Graceful shutdown, linger options and socket closure



Download 1.64 Mb.
Page12/49
Date31.07.2017
Size1.64 Mb.
#24975
1   ...   8   9   10   11   12   13   14   15   ...   49

62 Graceful shutdown, linger options and socket closure


Much confusion has been evidenced on the subject of shutting down socket connections and closing the sockets involved. Unless properly understood, the recent addition of WSASendDisconnect() and WSARecvDisconnect() could possibly exacerbate this situation. The following material is provided as clarification.
It is important to distinguish the difference between shutting down a socket connection and closing a socket. Shutting down a socket connection involves an exchange of protocol messages between the two endpoints which is hereafter referred to as a shutdown sequence. Two general classes of shutdown sequences are defined: graceful and abortive (also referred to as “hard”). In a graceful shutdown sequence, any data that has been queued but not yet transmitted can be sent prior to the connection being closed. In an abortive shutdown, any unsent data is lost. The occurrence of a shutdown sequence (graceful or abortive) can also be used to provide an FD_CLOSE indication to the associated applications signifying that a shutdown is in progress. Closing a socket, on the other hand, causes the socket handle to become deallocated so that the application can no longer reference or use the socket in any manner.
In Windows Sockets, both the shutdown() function, and the WSASendDisconnect() function can be used to initiate a shutdown sequence, while the closesocket() function is used to deallocate socket handles and free up any associated resources. Some amount of confusion arises, however, from the fact that the closesocket() function will implicitly cause a shutdown sequence to occur if it has not already happened. In fact, it has become a rather common programming practice to rely on this feature and use closesocket() to both initiate the shutdown sequence and deallocate the socket handle.
To facilitate this usage, the sockets interface provides for controls via the socket option mechanism that allows the programmer to indicate whether the implicit shutdown sequence should be graceful or abortive, and also whether the closesocket() function should linger (i.e. not complete immediately) to allow time for a graceful shutdown sequence to complete. Provided that the programmer fully understands the ramifications of using closesocket() in this manner, all is well. Unfortunately, many do not.
By establishing appropriate values for the socket options SO_LINGER and SO_DONTLINGER, the following types of behavior can be obtained with the closesocket() function.

  • Abortive shutdown sequence, immediate return from closesocket().

  • Graceful shutdown, delay return until either shutdown sequence completes or a specified time interval elapses. If the time interval expires before the graceful shutdown sequence completes, an abortive shutdown sequence occurs and closesocket() returns.

  • Graceful shutdown, return immediately and allow the shutdown sequence to complete in the background. This is the default behavior. Note, however, that the application has no way of knowing when (or whether) the graceful shutdown sequence completes.

One technique that can be used to minimize the chance of problems occurring during connection teardown is to not rely on an implicit shutdown being initiated by closesocket(). Instead one of the two explicit shutdown functions ( shutdown() or WSASendDisconnect() ) are used. This in turn will cause an FD_CLOSE indication to be received by the peer application indicating that all pending data has been received. To illustrate this, the following table shows the functions that would be invoked by the client and server components of an application, where the client is responsible for initiating a graceful shutdown.



Client Side

Server Side

(1) Invoke shutdown(s, SD_SEND) to signal end of session and that client has no more data to send.







(2) Receive FD_CLOSE, indicating graceful shutdown in progress and that all data has been received.




(3) Send any remaining response data.

(5’) Get FD_READ and invoke recv() to get any response data sent by server

(4) Invoke shutdown(s, SD_SEND) to indicate server has no more data to send.

(5) Receive FD_CLOSE indication

(4’) Invoke closesocket()

(6) Invoke closesocket()



Note that the timing sequence is maintained from step (1) to step (6) between the client and the server, except for step (4’) and (5’) which only has local timing significance in the sense that step (5) follows step (5’) on the client side while step (4’) follows step (4) on the server side, with no timing relationship with the remote party.



63 Out-Of-Band data


The stream socket abstraction includes the notion of "out of band'' (OOB) data. Many protocols allow

portions of incoming data to be marked as "special" in some way, and these special data blocks may be delivered to the user out of the normal sequence - examples include "expedited data" in X.25 and other OSI protocols, and BSD Unix's use of "urgent data" in TCP. This section describes OOB data handling in a protocol-independent manner - a discussion of OOB data implemented using TCP "urgent data" follows. Note that in the following, the use of recv() also implies recvfrom(), WSARecv(), and WSARecvFrom(), and references to WSAAsyncSelect() also apply to WSAEventSelect().



64 Protocol Independent OOB data

OOB data is a logically independent transmission channel associated with each pair of connected stream sockets. OOB data may be delivered to the user independently of normal data. The abstraction defines that the OOB data facilities must support the reliable delivery of at least one OOB data block at a time. This data block may contain at least one byte of data, and at least one OOB data block may be pending delivery to the user at any one time. For communications protocols which support in-band signaling (i.e. TCP, where the "urgent data" is delivered in sequence with the normal data), the system normally extracts the OOB data from the normal data stream and stores it separately (leaving a gap in the "normal" data stream). This allows users to choose between receiving the OOB data in order and receiving it out of sequence without having to buffer all the intervening data. It is possible to "peek'' at out-of-band data.


A user can determine if there is any OOB data waiting to be read using the ioctlsocket(SIOCATMARK) function (q.v.). For protocols where the concept of the "position" of the OOB data block within the normal data stream is meaningful (i.e. TCP), a Windows Sockets service provider will maintain a conceptual "marker" indicating the position of the last byte of OOB data within the normal data stream. This is not necessary for the implementation of the ioctlsocket(SIOCATMARK) functionality - the presence or absence of OOB data is all that is required.
For protocols where the concept of the "position" of the OOB data block within the normal data stream is meaningful an application may prefer to process out-of-band data "in-line", as part of the normal data stream. This is achieved by setting the socket option SO_OOBINLINE (see section 88 , setsockopt()). For other protocols where the OOB data blocks are truly independent of the normal data stream, attempting to set SO_OOBINLINE will result in an error. An application can use the SIOCATMARK ioctlsocket() command (see section 79 ) to determine whether there is any unread OOB data preceding the mark. For example, it might use this to resynchronize with its peer by ensuring that all data up to the mark in the data stream is discarded when appropriate.
With SO_OOBINLINE disabled (the default setting):

· WinSock notifies an application of an FD_OOB event, if the application registered for notification with WSAAsyncSelect(), in exactly the same way FD_READ is used to notify of the presence of normal data. That is, FD_OOB is posted when OOB data arrives and there was no OOB data previously queued, and also when data is read using the MSG_OOB flag, and some OOB data remains to be read after the read operation has returned. FD_READ messages are not posted for OOB data.

· WinSock returns from select() with the appropriate exceptfds socket set if OOB data is queued on the socket.

· the application can call recv() with MSG_OOB to read the urgent data block at any time. The block of OOB data "jumps the queue".

· the application can call recv() without MSG_OOB to read the normal data stream. The OOB data block will not appear in the data stream with "normal data." If OOB data remains after any call to recv(), WinSock notifies the application with FD_OOB or via exceptfds when using select().

· For protocols where the OOB data has a position within the normal data stream, a single recv() operation will not span that position. One recv() will return the normal data before the "mark", and a second recv() is required to begin reading data after the "mark".


With SO_OOBINLINE enabled:

· FD_OOB messages are _NOT_ posted for OOB data - for the purpose of the select() and WSAAsyncSelect() functions, OOB data is treated as normal data, and indicated by setting the socket in readfds or by sending an FD_READ message respectively.

· the application may not call recv() with the MSG_OOB flag set to read the OOB data block - the error code WSAEINVAL will be returned.

· the application can call recv() without the MSG_OOB flag set. Any OOB data will be delivered in its correct order within the "normal" data stream. OOB data will never be mixed with normal data - there must be three read requests to get past the OOB data. The first returns the normal data prior to the OOB data block, the second returns the OOB data, the third returns the normal data following the OOB data. In other words, the OOB data block boundaries are preserved.



The WSAAsyncSelect() routine is particularly well suited to handling notification of the presence of out-of-band-data when SO_OOBINLINE is off.

65 OOB data in TCP


Note: The following discussion of out-of-band (OOB) data, implemented using TCP Urgent data, follows the model used in the Berkeley software distribution. Users and implementors should be aware of the fact that there are at present two conflicting interpretations of RFC 793 (in which the concept is introduced), and that the implementation of out-of-band data in the Berkeley Software Distribution (BSD) does not conform to the Host Requirements laid down in RFC 1122.
Specifically, the TCP urgent pointer in BSD points to the byte after the urgent data byte, and an RFC-compliant TCP urgent pointer points to the urgent data byte. As a result, if an application sends urgent data from a BSD-compatible implementation to an RFC-1122 compatible implementation then the receiver will read the wrong urgent data byte (it will read the byte located after the correct byte in the data stream as the urgent data byte).
To minimize interoperability problems, applications writers are advised not to use out-of-band data unless this is required in order to interoperate with an existing service. Windows Sockets suppliers are urged to document the out-of-band semantics (BSD or RFC 1122) which their product implements.
Arrival of a TCP segment with the "URG"ent flag set indicates the existence of a single byte of "OOB" data within the TCP data stream. The "OOB data block" is one byte in size. The urgent pointer is a positive offset from the current sequence number in the TCP header that indicates the location of the "OOB data block" (ambiguously, as noted above). This may point to data that has not yet been received.
With SO_OOBINLINE disabled (the default), when the TCP segment containing the byte pointed to by the urgent pointer arrives, the OOB data block (one byte) is removed from the data stream and buffered. If a subsequent TCP segment arrives with the urgent flag set (and a new urgent pointer), the OOB byte currently queued may be lost as it is replaced by the new OOB data block (as occurs in Berkeley Software Distribution). It is never replaced in the data stream, however.
With SO_OOBINLINE enabled, the urgent data remains in the data stream. As a result, the OOB data block is never lost when a new TCP segment arrives containing urgent data. The existing OOB data "mark" is updated to the new position.


Download 1.64 Mb.

Share with your friends:
1   ...   8   9   10   11   12   13   14   15   ...   49




The database is protected by copyright ©ininet.org 2024
send message

    Main page