Windows Sockets
An Open Interface for Network Programming under Microsoft Windows
Version 1.1
20 January 1993
Table of Contents
3. SOCKET LIBRARY OVERVIEW
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.
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.
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.
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
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
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.
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.
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.
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.
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.
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