Windows Sockets

An Open Interface for Network Programming under Microsoft Windows

Version 1.1

20 January 1993

Table of Contents


3. SOCKET LIBRARY OVERVIEW

3.1 Socket Functions

The Windows Sockets specification includes the following Berkeley-style socket routines:
accept() *
An incoming connection is acknowledged and associated with an immediately created socket. The original socket is returned to the listening state.

bind()
Assign a local name to an unnamed socket.

closesocket() *
Remove a socket from the per-process object reference table. Only blocks if SO_LINGER is set.

connect() *
Initiate a connection on the specified socket.

getpeername()
Retrieve the name of the peer connected to the specified socket.

getsockname()
Retrieve the current name for the specified socket

getsockopt()
Retrieve options associated with the specified socket.

htonl()
Convert a 32-bit quantity from host byte order to network byte order.

htons()
Convert a 16-bit quantity from host byte order to network byte order.

inet_addr()
Converts a character string representing a number in the Internet standard ".'' notation to an Internet address value.

inet_ntoa()
Converts an Internet address value to an ASCII string in ".'' notation i.e. "a.b.c.d''.

ioctlsocket()
Provide control for sockets.

listen()
Listen for incoming connections on a specified socket.

ntohl()
Convert a 32-bit quantity from network byte order to host byte order.

ntohs()
Convert a 16-bit quantity from network byte order to host byte order.

recv() *
Receive data from a connected socket.

recvfrom() *
Receive data from either a connected or unconnected socket.

select() *
Perform synchronous I/O multiplexing.

send() *
Send data to a connected socket.

sendto() *
Send data to either a connected or unconnected socket.

setsockopt()
Store options associated with the specified socket.

shutdown()
Shut down part of a full-duplex connection.

socket()
Create an endpoint for communication and return a socket.

* = The routine can block if acting on a blocking socket.

3.1.1 Blocking/Non blocking & Data Volatility

One major issue in porting applications from a Berkeley sockets environment to a Windows environment involves "blocking"; that is, invoking a function which does not return until the associated operation is completed. The problem arises when the operation may take an arbitrarily long time to complete: an obvious example is a recv() which may block until data has been received from the peer system. The default behavior within the Berkeley sockets model is for a socket to operate in a blocking mode unless the programmer explicitly requests that operations be treated as non-blocking. It is strongly recommended that programmers use the nonblocking (asynchronous) operations if at all possible, as they work significantly better within the nonpreemptive Windows environment. Use blocking operations only if absolutely necessary, and carefully read and understand this section if you must use blocking operations.

Even on a blocking socket, some operations (e.g. bind(), getsockopt(), getpeername()) can be completed immediately. For such operations there is no difference between blocking and non-blocking operation. Other operations (e.g. recv()) may be completed immediately or may take an arbitrary time to complete, depending on various transport conditions. When applied to a blocking socket, these operations are referred to as blocking operations. All routines which can block are listed with an asterisk in the tables above and below.

Within a Windows Sockets implementation, a blocking operation which cannot be completed immediately is handled as follows. The DLL initiates the operation, and then enters a loop in which it dispatches any Windows messages (yielding the processor to another thread if necessary) and then checks for the completion of the Windows Sockets function. If the function has completed, or if WSACancelBlockingCall() has been invoked, the blocking function completes with an appropriate result. Refer to section 4.3.13, WSASetBlockingHook(), for a complete description of this mechanism, including pseudocode for the various functions.

If a Windows message is received for a process for which a blocking operation is in progress, there is a risk that the application will attempt to issue another Windows Sockets call. Because of the difficulty of managing this condition safely, the Windows Sockets specification does not support such application behavior. Two functions are provided to assist the programmer in this situation. WSAIsBlocking() may be called to determine whether or not a blocking Windows Sockets call is in progress. WSACancelBlockingCall() may be called to cancel an in-progress blocking call, if any. Any other Windows Sockets function which is called in this situation will fail with the error WSAEINPROGRESS. It should be emphasized that this restriction applies to both blocking and non-blocking operations.

Although this mechanism is sufficient for simple applications, it cannot support the complex message- dispatching requirements of more advanced applications (for example, those using the MDI model). For such applications, the Windows Sockets API includes the function WSASetBlockingHook(), which allows the programmer to define a special routine which will be called instead of the default message dispatch routine described above.

The Windows Sockets DLL calls the blocking hook only if all of the following are true: the routine is one which is defined as being able to block, the specified socket is a blocking socket, and the request cannot be completed immediately. (A socket is set to blocking by default, but the IOCTL FIONBIO and WSAAsyncSelect() both set a socket to nonblocking mode.) If an application uses only non-blocking sockets and uses the WSAAsyncSelect() and/or the WSAAsyncGetXByY() routines instead of select() and the getXbyY() routines, then the blocking hook will never be called and the application does not need to be concerned with the reentrancy issues the blocking hook can introduce.

If an application invokes an asynchronous or non-blocking operation which takes a pointer to a memory object (e.g. a buffer, or a global variable) as an argument, it is the responsibility of the application to ensure that the object is available to the Windows Sockets implementation throughout the operation. The application must not invoke any Windows function which might affect the mapping or addressability of the memory involved. In a multithreaded system, the application is also responsible for coordinating access to the object using appropriate synchronization mechanisms. A Windows Sockets implementation cannot, and will not, address these issues. The possible consequences of failing to observe these rules are beyond the scope of this specification.

3.2 Database Functions

The Windows Sockets specification defines the following "database" routines. As noted earlier, a Windows Sockets supplier may choose to implement these in a manner which does not depend on local database files. The pointer returned by certain database routines such as gethostbyname() points to a structure which is allocated by the Windows Sockets library. The data which is pointed to is volatile and is good only until the next Windows Sockets API call from that thread. Additionally, the application must never attempt to modify this structure or to free any of its components. Only one copy of this structure is allocated for a thread, and so the application should copy any information which it needs before issuing any other Windows Sockets API calls.

gethostbyaddr() *
Retrieve the name(s) and address corresponding to a network address.

gethostbyname() *
Retrieve the name(s) and address corresponding to a host name.

gethostname()
Retrieve the name of the local host.

getprotobyname() *
Retrieve the protocol name and number corresponding to a protocol name.

getprotobynumber() *
Retrieve the protocol name and number corresponding to a protocol number.

getservbyname() *
Retrieve the service name and port corresponding to a service name.

getservbyport() *
Retrieve the service name and port corresponding to a port.

* = The routine can block under some circumstances.

3.3 Microsoft Windows-specific Extension Functions

The Windows Sockets specification provides a number of extensions to the standard set of Berkeley Sockets routines. Principally, these extended APIs allow message-based, asynchronous access to network events. While use of this extended API set is not mandatory for socket-based programming (with the exception of WSAStartup() and WSACleanup()), it is recommended for conformance with the Microsoft Windows programming paradigm.

WSAAsyncGetHostByAddr()
A set of functions which provide asynchronous

WSAAsyncGetHostByName()
versions of the standard Berkeley

WSAAsyncGetProtoByName()
getXbyY() functions. For example, the

WSAAsyncGetProtoByNumber()
WSAAsyncGetHostByName() function provides an

WSAAsyncGetServByName()
asynchronous message based implementation of

WSAAsyncGetServByPort()
the standard Berkeley gethostbyname() function.

WSAAsyncSelect()
Perform asynchronous version of select()

WSACancelAsyncRequest()
Cancel an outstanding instance of a WSAAsyncGetXByY() function.

WSACancelBlockingCall()
Cancel an outstanding "blocking" API call

WSACleanup()
Sign off from the underlying Windows Sockets DLL.

WSAGetLastError()
Obtain details of last Windows Sockets API error

WSAIsBlocking()
Determine if the underlying Windows Sockets DLL is already blocking an existing call for this thread

WSASetBlockingHook()
"Hook" the blocking method used by the underlying Windows Sockets implementation

WSASetLastError()
Set the error to be returned by a subsequent WSAGetLastError()

WSAStartup()
Initialize the underlying Windows Sockets DLL.

WSAUnhookBlockingHook()
Restore the original blocking function

3.3.1 Asynchronous select() Mechanism

The WSAAsyncSelect() API allows an application to register an interest in one or many network events. This API is provided to supersede the need to do polled network I/O. Any situation in which select() or non-blocking I/O routines (such as send() and recv()) are either already used or are being considered is usually a candidate for the WSAAsyncSelect() API. When declaring interest in such condition(s), you supply a window handle to be used for notification. The corresponding window then receives message- based notification of the conditions in which you declared an interest.

WSAAsyncSelect() allows interest to be declared in the following conditions for a particular socket: Socket readiness for reading Socket readiness for writing Out-of-band data ready for reading Socket readiness for accepting incoming connection Completion of non-blocking connect() Connection closure

3.3.2 Asynchronous Support Routines

The asynchronous "database" functions allow applications to request information in an asynchronous manner. Some network implementations and/or configurations perform network based operations to resolve such requests. The WSAAsyncGetXByY() functions allow application developers to request services which would otherwise block the operation of the whole Windows environment if the standard Berkeley function were used. The WSACancelAsyncRequest() function allows an application to cancel any outstanding asynchronous request.

3.3.3 Hooking Blocking Methods

As noted in section 3.1.1 above, Windows Sockets implements blocking operations in such a way that Windows message processing can continue, which may result in the application which issued the call receiving a Windows message. In certain situations an application may want to influence or change the way in which this pseudo-blocking process is implemented. The WSASetBlockingHook() provides the ability to substitute a named routine which the Windows Sockets implementation is to use when relinquishing the processor during a "blocking" operation.

3.3.4 Error Handling

For compatibility with thread-based environments, details of API errors are obtained through the WSAGetLastError() API. Although the accepted "Berkeley-Style" mechanism for obtaining socket-based network errors is via "errno", this mechanism cannot guarantee the integrity of an error ID in a multi- threaded environment. WSAGetLastError() allows you to retrieve an error code on a per thread basis.

WSAGetLastError() returns error codes which avoid conflict with standard Microsoft C error codes. Certain error codes returned by certain Windows Sockets routines fall into the standard range of error codes as defined by Microsoft C. If you are NOT using an application development environment which defines error codes consistent with Microsoft C, you are advised to use the Windows Sockets error codes prefixed by "WSA" to ensure accurate error code detection.

Note that this specification defines a recommended set of error codes, and lists the possible errors which may be returned as a result of each function. It may be the case in some implementations that other Windows Sockets error codes will be returned in addition to those listed, and applications should be prepared to handle errors other than those enumerated under each API description. However a Windows Sockets implementation must not return any value which is not enumerated in the table of legal Windows Sockets errors given in Appendix A.1.

3.3.5 Accessing a Windows Sockets DLL from an Intermediate DLL

A Windows Sockets DLL may be accessed both directly from an application and through an "intermediate" DLL. An example of such an intermediate DLL would be a virtual network API layer that supports generalized network functionality for applications and uses Windows Sockets. Such a DLL could be used by several applications simultaneously, and the DLL must take special precautions with respect to the WSAStartup() and WSACleanup() calls to ensure that these routines are called in the context of each task that will make Windows Sockets calls. This is because the Windows Sockets DLL will need a call to WSAStartup() for each task in order to set up task-specific data structures, and a call to WSACleanup() to free any resources allocated for the task.

There are (at least) two ways to accomplish this. The simplest method is for the intermediate DLL to have calls similar to WSAStartup() and WSACleanup() that applications call as appropriate. The DLL would then call WSAStartup() or WSACleanup() from within these routines. Another mechanism is for the intermediate DLL to build a table of task handles, which are obtained from the GetCurrentTask() Windows API, and at each entry point into the intermediate DLL check whether WSAStartup() has been called for the current task, then call WSAStartup() if necessary.

If a DLL makes a blocking call and does not install its own blocking hook, then the DLL author must be aware that control may be returned to the application either by an application-installed blocking hook or by the default blocking hook. Thus, it is possible that the application will cancel the DLL's blocking operation via WSACancelBlockingCall(). If this occurs, the DLL's blocking operation will fail with the error code WSAEINTR, and the DLL must return control to the calling task as quickly as possible, as the used has likely pressed a cancel or close button and the task has requested control of the CPU. It is recommended that DLLs which make blocking calls install their own blocking hooks with WSASetBlockingHook() to prevent unforeseen interactions between the application and the DLL.

Note that this is not necessary for DLLs in Windows NT because of its different process and DLL structure. Under Windows NT, the intermediate DLL could simply call WSAStartup() in its DLL initialization routine, which is called whenever a new process which uses the DLL starts.

3.3.6 Internal use of Messages by Windows Sockets Implementations

In order to implement Windows Sockets purely as a DLL, it may be necessary for the DLL to post messages internally for communication and timing. This is perfectly legal; however, a Windows Sockets DLL must not post messages to a window handle opened by a client application except for those messages requested by the application. A Windows Sockets DLL that needs to use messages for its own purposes must open a hidden window and post any necessary messages to the handle for that window.

3.3.7 Private API Interfaces

The winsock.def file in Appendix B.7 lists the ordinals defined for the Windows Sockets APIs. In addition to the ordinal values listed, all ordinals 999 and below are reserved for future Windows Sockets use. It may be convenient for a Windows Sockets implementation to export additional, private interfaces from the Windows Sockets DLL. This is perfectly acceptable, as long as the ordinals for these exports are above 1000. Note that any application that uses a particular Windows Sockets DLL's private APIs will most likely not work on any other vendor's Windows Sockets implementation. Only the APIs defined in this document are guaranteed to be present in every Windows Sockets implementation.

If an application uses private interfaces of a particular vendor's Windows Sockets DLL, it is recommended that the DLL not be statically linked with the application but rather dynamically loaded with the Windows routines LoadLibrary() and GetProcAddress(). This allows the application to give an informative error message if it is run on a system with a Windows Sockets DLL that does not support the same set of extended functionality.


NEXT PREVIOUS CONTENTS