Windows Sockets
An Open Interface for Network Programming under Microsoft Windows
Version 1.1
20 January 1993
This version of the Windows Sockets specification does not attempt to address explicitly the issue of multiple concurrent Windows Sockets implementations. Nothing in the specification should be interpreted as restricting multiple Windows Sockets DLLs from being present and used concurrently by one or more Windows Sockets applications.
For further details of where to obtain Windows Sockets components, see Appendix B.2.
Sockets are typed according to the communication properties visible to a user. Applications are presumed to communicate only between sockets of the same type, although there is nothing that prevents communication between sockets of different types should the underlying communication protocols support this.
Two types of sockets currently are available to a user. A stream socket provides for the bi-directional, reliable, sequenced, and unduplicated flow of data without record boundaries.
A datagram socket supports bi-directional flow of data which is not promised to be sequenced, reliable, or unduplicated. That is, a process receiving messages on a datagram socket may find messages duplicated, and, possibly, in an order different from the order in which it was sent. An important characteristic of a datagram socket is that record boundaries in data are preserved. Datagram sockets closely model the facilities found in many contemporary packet switched networks such as Ethernet.
The client and server require a well-known set of conventions before service may be rendered (and accepted). This set of conventions comprises a protocol which must be implemented at both ends of a connection. Depending on the situation, the protocol may be symmetric or asymmetric. In a symmetric protocol, either side may play the master or slave roles. In an asymmetric protocol, one side is immutably recognized as the master, with the other as the slave. An example of a symmetric protocol is the TELNET protocol used in the Internet for remote terminal emulation. An example of an asymmetric protocol is the Internet file transfer protocol, FTP. No matter whether the specific protocol used in obtaining a service is symmetric or asymmetric, when accessing a service there is a "client process'' and a "server process''.
A server application normally listens at a well-known address for service requests. That is, the server process remains dormant until a connection is requested by a client's connection to the server's address. At such a time the server process "wakes up'' and services the client, performing whatever appropriate actions the client requests of it. While connection-based services are the norm, some services are based on the use of datagram sockets.
The stream socket abstraction includes the notion of "out of band'' data. Out-of-band data is a logically independent transmission channel associated with each pair of connected stream sockets. Out-of-band data is delivered to the user independently of normal data. The abstraction defines that the out-of-band data facilities must support the reliable delivery of at least one out-of-band message at a time. This message may contain at least one byte of data, and at least one message may be pending delivery to the user at any one time. For communications protocols which support only in-band signaling (i.e. the urgent data is delivered in sequence with the normal data), the system normally extracts the data from the normal data stream and stores it separately. This allows users to choose between receiving the urgent 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.
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 4.1.21, setsockopt()). In this case, the application may wish to determine whether any of the unread data is "urgent" (the term usually applied to in-line out-of-band data). To facilitate this, the Windows Sockets implementation will maintain a logical "mark" in the data stream indicate the point at which the out-of-band data was sent. An application can use the SIOCATMARK ioctlsocket() command (see section 4.1.12) to determine whether there is any unread 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.
The WSAAsyncSelect() routine is particularly well suited to handling notification of the presence of out- of-band-data.
The destination address of the message to be broadcast depends on the network(s) on which the message is to be broadcast. The Internet domain supports a shorthand notation for broadcast on the local network, the address INADDR_BROADCAST. Received broadcast messages contain the senders address and port, as datagram sockets must be bound before use.
Some types of network support the notion of different types of broadcast. For example, the IEEE 802.5 token ring architecture supports the use of link-level broadcast indicators, which control whether broadcasts are forwarded by bridges. The Windows Sockets specification does not provide any mechanism whereby an application can determine the type of underlying network, nor any way to control the semantics of broadcasting.
Any reference to IP addresses or port numbers passed to or from a Windows Sockets routine must be in network order. This includes the IP address and port fields of a struct sockaddr_in (but not the sin_family field).
Consider an application which normally contacts a server on the TCP port corresponding to the "time" service, but which provides a mechanism for the user to specify that an alternative port is to be used. The port number returned by getservbyname() is already in network order, which is the format required constructing an address, so no translation is required. However if the user elects to use a different port, entered as an integer, the application must convert this from host to network order (using the htons() function) before using it to construct an address. Conversely, if the application wishes to display the number of the port within an address (returned via, e.g., getpeername()), the port number must be converted from network to host order (using ntohs()) before it can be displayed.
Since the Intel and Internet byte orders are different, the conversions described above are unavoidable. Application writers are cautioned that they should use the standard conversion functions provided as part of the Windows Sockets API rather than writing their own conversion code, since future implementations of Windows Sockets are likely to run on systems for which the host order is identical to the network byte order. Only applications which use the standard conversion functions are likely to be portable.
Value | Type | Meaning | Default | Note |
SO_ACCEPTCONN | BOOL | Socket is listen()ing. | FALSE unless a listen() has been performed | |
SO_BROADCAST | BOOL | Socket is configured for the transmission of broadcast messages. | FALSE | |
SO_DEBUG | BOOL | Debugging is enabled. | FALSE | (i) |
SO_DONTLINGER | BOOL | If true, the SO_LINGER option is disabled. | TRUE | |
SO_DONTROUTE | BOOL | Routing is disabled. | FALSE | (i) |
SO_ERROR | int | Retrieve error status and clear. | 0 | |
SO_KEEPALIVE | BOOL | Keepalives are being sent. | FALSE | |
SO_LINGER | struct linger FAR * | Returns the current linger options. | l_onoff is 0 | |
SO_OOBINLINE | BOOL | Out-of-band data is being received in the normal data stream. | FALSE | |
SO_RCVBUF | int | Buffer size for receives | Implementation dependent | (i) |
SO_REUSEADDR | BOOL | The address to which this socket is bound can be used by others. | FALSE | |
SO_SNDBUF | int | Buffer size for sends | Implementation dependent | (i) |
SO_TYPE | int | The type of the socket (e.g. SOCK_STREAM). | As created via socket() | |
TCP_NODELAY | BOOL | Disables the Nagle algorithm for send coalescing. | Implementation dependent |
In UNIX, all handles, including socket handles, are small, non-negative integers, and some applications make assumptions that this will be true. Windows Sockets handles have no restrictions, other than that the value INVALID_SOCKET is not a valid socket. Socket handles may take any value in the range 0 to INVALID_SOCKET-1.
Because the SOCKET type is unsigned, compiling existing source code from, for example, a UNIX environment may lead to compiler warnings about signed/unsigned data type mismatches.
This means, for example, that checking for errors when the socket() and accept() routines return should not be done by comparing the return value with -1, or seeing if the value is negative (both common, and legal, approaches in BSD). Instead, an application should use the manifest constant INVALID_SOCKET as defined in winsock.h. For example:
TYPICAL BSD STYLE:
s = socket(...); if (s == -1) /* or s < 0 */ {...}
PREFERRED STYLE:
s = socket(...); if (s == INVALID_SOCKET) {...}
For compatibility with BSD, an application may choose to include a line of the form:
#define errno WSAGetLastError()This will allow networking code which was written to use the global errno to work correctly in a single- threaded environment. There are, obviously, some drawbacks. If a source file includes code which inspects errno for both socket and non-socket functions, this mechanism cannot be used. Furthermore, it is not possible for an application to assign a new value to errno. (In Windows Sockets the function WSASetLastError() may be used for this purpose.)
TYPICAL BSD STYLE:
r = recv(...); if (r == -1 && errno == EWOULDBLOCK) {...}PREFERRED STYLE:
r = recv(...); if (r == -1 /* (but see below) */ && WSAGetLastError() == EWOULDBLOCK) {...}Although error constants consistent with 4.3 Berkeley Sockets are provided for compatibility purposes, applications should, where possible, use the "WSA" error code definitions. For example, a more accurate version of the above source code fragment is:
r = recv(...); if (r == -1 /* (but see below) */ && WSAGetLastError() == WSAEWOULDBLOCK) {...}
The maximum number of sockets which a Windows Sockets application can make use of is determined at compile time by the manifest constant FD_SETSIZE. This value is used in constructing the fd_set structures used in select() (see section 4.1.18). The default value in winsock.h is 64. If an application is designed to be capable of working with more than 64 sockets, the implementor should define the manifest FD_SETSIZE in every source file before including winsock.h. One way of doing this may be to include the definition within the compiler options in the makefile, for example adding -DFD_SETSIZE=128 as an option to the compiler command line for Microsoft C. It must be emphasized that defining FD_SETSIZE as a particular value has no effect on the actual number of sockets provided by a Windows Sockets implementation.
TYPICAL BSD STYLE:
r = recv(...); if (r == -1 /* or r < 0 */ && errno == EWOULDBLOCK) {...}PREFERRED STYLE:
r = recv(...); if (r == SOCKET_ERROR && WSAGetLastError() == WSAEWOULDBLOCK) {...}
Closing a socket in one thread that has an outstanding blocking call on the same socket in another thread will cause the blocking call to fail with WSAEINTR, just as if the operation were canceled. This also applies if there is a select() call outstanding and the application closes one of the sockets being selected.
There is no default blocking hook installed in preemptive multithreaded versions of Windows. This is because the machine will not be blocked if a single application is waiting for an operation to complete and hence not calling PeekMessage() or GetMessage() which cause the application to yield in nonpremptive Windows. However, for backwards compatibility the WSASetBlockingHook() call is implemented in multithreaded versions of Windows, and any application whose behavior depends on the default blocking hook may install their own blocking hook which duplicates the default hook's semantics, if desired.