Windows Sockets
An Open Interface for Network Programming under Microsoft Windows
Version 1.1
20 January 1993
In each routine it is indicated that the header file winsock.h must be included. Appendix A.2 lists the Berkeley-compatible header files which are supported. These are provided for compatibility purposes only, and each of them will simply include winsock.h. The Windows header file windows.h is also needed, but winsock.h will include it if necessary.
#include <winsock.h> SOCKET PASCAL FAR accept ( SOCKET s, struct sockaddr FAR * addr, int FAR * addrlen );
The argument addr is a result parameter that is filled in with the address of the connecting entity, as known to the communications layer. The exact format of the addr parameter is determined by the address family in which the communication is occurring. The addrlen is a value-result parameter; it should initially contain the amount of space pointed to by addr; on return it will contain the actual length (in bytes) of the address returned. This call is used with connection-based socket types such as SOCK_STREAM. If addr and/or addrlen are equal to NULL, then no information about the remote address of the accepted socket is returned.
The integer referred to by addrlen initially contains the amount of space pointed to by addr. On return it will contain the actual length in bytes of the address returned.
#include <winsock.h> int PASCAL FAR bind ( SOCKET s, const struct sockaddr FAR * name, int namelen );
struct sockaddr { u_short sa_family; char sa_data[14]; };
In the Internet address family, a name consists of several components. For SOCK_DGRAM and SOCK_STREAM, the name consists of three parts: a host address, the protocol number (set implicitly to UDP or TCP, respectively), and a port number which identifies the application. If an application does not care what address is assigned to it, it may specify an Internet address equal to INADDR_ANY, a port equal to 0, or both. If the Internet address is equal to INADDR_ANY, any appropriate network interface will be used; this simplifies application programming in the presence of multi- homed hosts. If the port is specified as 0, the Windows Sockets implementation will assign a unique port to the application with a value between 1024 and 5000. The application may use getsockname() after bind() to learn the address that has been assigned to it, but note that getsockname() will not necessarily fill in the Internet address until the socket is connected, since several Internet addresses may be valid if the host is multi-homed.
If an application desires to bind to an arbitrary port outside of the range 1024 to 5000, such as the case of rsh which must bind to any reserved port, code similar to the following may be used:
SOCKADDR_IN sin; SOCKET s; u_short alport = IPPORT_RESERVED; sin.sin_family = AF_INET; sin.sin_addr.s_addr = 0; for (;;) { sin.sin_port = htons(alport); if (bind(s, (LPSOCKADDR)&sin, sizeof (sin)) == 0) { /* it worked */ } if ( GetLastError() != WSAEADDRINUSE) { /* fail */ } alport--; if (alport == IPPORT_RESERVED/2 ) { /* fail--all unassigned reserved ports are */ /* in use. */ } }
#include <winsock.h> int PASCAL FAR closesocket ( SOCKET s );
The semantics of closesocket() are affected by the socket options SO_LINGER and SO_DONTLINGER as follows:
Option Interval Type of close Wait for close? SO_DONTLINGER Don't care Graceful No SO_LINGER Zero Hard No SO_LINGER Non-zero Graceful YesIf SO_LINGER is set (i.e. the l_onoff field of the linger structure is non-zero; see sections 2.4, 4.1.7 and 4.1.21) with a zero timeout interval (l_linger is zero), closesocket() is not blocked even if queued data has not yet been sent or acknowledged. This is called a "hard" or "abortive" close, because the socket's virtual circuit is reset immediately, and any unsent data is lost. Any recv() call on the remote side of the circuit will fail with WSAECONNRESET.
If SO_LINGER is set with a non-zero timeout interval, the closesocket() call blocks until the remaining data has been sent or until the timeout expires. This is called a graceful disconnect. Note that if the socket is set to non-blocking and SO_LINGER is set to a non-zero timeout, the call to closesocket() will fail with an error of WSAEWOULDBLOCK.
If SO_DONTLINGER is set on a stream socket (i.e. the l_onoff field of the linger structure is zero; see sections 2.4, 4.1.7 and 4.1.21), the closesocket() call will return immediately. However, any data queued for transmission will be sent if possible before the underlying socket is closed. This is also called a graceful disconnect. Note that in this case the Windows Sockets implementation may not release the socket and other resources for an arbitrary period, which may affect applications which expect to use all available sockets.
#include <winsock.h> int PASCAL FAR connect ( SOCKET s, const struct sockaddr FAR * name, int namelen );
For stream sockets (type SOCK_STREAM), an active connection is initiated to the foreign host using name (an address in the name space of the socket). When the socket call completes successfully, the socket is ready to send/receive data.
For a datagram socket (type SOCK_DGRAM), a default destination is set, which will be used on subsequent send() and recv() calls.
On a blocking socket, the return value indicates success or failure of the connection attempt.
On a non-blocking socket, if the return value is SOCKET_ERROR an application should call WSAGetLastError(). If this indicates an error code of WSAEWOULDBLOCK, then your application can either:
#include <winsock.h> int PASCAL FAR getpeername ( SOCKET s, struct sockaddr FAR * name, int FAR * namelen );
On return, the namelen argument contains the actual size of the name returned in bytes.
#include <winsock.h> int PASCAL FAR getsockname ( SOCKET s, struct sockaddr FAR * name, int FAR * namelen );
On return, the namelen argument contains the actual size of the name returned in bytes.
If a socket was bound to INADDR_ANY, indicating that any of the host's IP addresses should be used for the socket, getsockname() will not necessarily return information about the host IP address, unless the socket has been connected with connect() or accept(). A Windows Sockets application must not assume that the IP address will be changed from INADDR_ANY unless the socket is connected. This is because for a multi-homed host the IP address that will be used for the socket is unknown unless the socket is connected.
#include <winsock.h> int PASCAL FAR getsockopt ( SOCKET s, int level, int optname, char FAR * optval, int FAR * optlen );
The value associated with the selected option is returned in the buffer optval. The integer pointed to by optlen should originally contain the size of this buffer; on return, it will be set to the size of the value returned. For SO_LINGER, this will be the size of a struct linger; for all other options it will be the size of an integer.
If the option was never set with setsockopt(), then getsockopt() returns the default value for the option.
The following options are supported for getsockopt(). The Type identifies the type of data addressed by optval. The TCP_NODELAY option uses level IPPROTO_TCP; all other options use level SOL_SOCKET.
Value Type Meaning SO_ACCEPTCONN BOOL Socket is listen()ing. SO_BROADCAST BOOL Socket is configured for the transmission of broadcast messages. SO_DEBUG BOOL Debugging is enabled. SO_DONTLINGER BOOL If true, the SO_LINGER option is disabled. SO_DONTROUTE BOOL Routing is disabled. SO_ERROR int Retrieve error status and clear. SO_KEEPALIVE BOOL Keepalives are being sent. SO_LINGER struct linger Returns the current linger options. FAR * SO_OOBINLINE BOOL Out-of-band data is being received in the normal data stream. SO_RCVBUF int Buffer size for receives SO_REUSEADDR BOOL The socket may be bound to an address which is already in use. SO_SNDBUF int Buffer size for sends SO_TYPE int The type of the socket (e.g. SOCK_STREAM). TCP_NODELAY BOOL Disables the Nagle algorithm for send coalescing.BSD options not supported for getsockopt() are:
Value Type Meaning SO_RCVLOWAT int Receive low water mark SO_RCVTIMEO int Receive timeout SO_SNDLOWAT int Send low water mark SO_SNDTIMEO int Send timeout IP_OPTIONS Get options in IP header. TCP_MAXSEG int Get TCP maximum segment size.Calling getsockopt() with an unsupported option will result in an error code of WSAENOPROTOOPT being returned from WSAGetLastError().
#include <winsock.h> u_long PASCAL FAR htonl ( u_long hostlong );
#include <winsock.h> u_short PASCAL FAR htons ( u_short hostshort );
#include <winsock.h> unsigned long PASCAL FAR inet_addr ( const char FAR * cp );
Internet Addresses
Values specified using the ".'' notation take one of the following forms:
a.b.c.d a.b.c a.b aWhen four parts are specified, each is interpreted as a byte of data and assigned, from left to right, to the four bytes of an Internet address. Note that when an Internet address is viewed as a 32-bit integer quantity on the Intel architecture, the bytes referred to above appear as "d.c.b.a''. That is, the bytes on an Intel processor are ordered from right to left.
Note: The following notations are only used by Berkeley, and nowhere else on the Internet. In the interests of compatibility with their software, they are supported as specified.
When a three part address is specified, the last part is interpreted as a 16-bit quantity and placed in the right most two bytes of the network address. This makes the three part address format convenient for specifying Class B network addresses as "128.net.host''.
When a two part address is specified, the last part is interpreted as a 24-bit quantity and placed in the right most three bytes of the network address. This makes the two part address format convenient for specifying Class A network addresses as "net.host''.
When only one part is given, the value is stored directly in the network address without any byte rearrangement.
#include <winsock.h> char FAR * PASCAL FAR inet_ntoa ( struct in_addr in );
#include <winsock.h> int PASCAL FAR ioctlsocket ( SOCKET s, long cmd, u_long FAR * argp );
The WSAAsyncSelect() routine automatically sets a socket to nonblocking mode. If WSAAsyncSelect() has been issued on a socket, then any attempt to use ioctlsocket() to set the socket back to blocking mode will fail with WSAEINVAL. To set the socket back to blocking mode, an application must first disable WSAAsyncSelect() by calling WSAAsyncSelect() with the lEvent parameter equal to 0.
#include <winsock.h> int PASCAL FAR listen ( SOCKET s, int backlog );
This function is typically used by servers that could have more than one connection request at a time: if a connection request arrives with the queue full, the client will receive an error with an indication of WSAECONNREFUSED.
listen() attempts to continue to function rationally when there are no available descriptors. It will accept connections until the queue is emptied. If descriptors become available, a later call to listen() or accept() will re-fill the queue to the current or most recent "backlog'', if possible, and resume listening for incoming connections.
#include <winsock.h> u_long PASCAL FAR ntohl ( u_long netlong );
#include <winsock.h> u_short PASCAL FAR ntohs ( u_short netshort );
#include <winsock.h> int PASCAL FAR recv ( SOCKET s, char FAR * buf, int len, int flags );
For sockets of type SOCK_STREAM, as much information as is currently available up to the size of the buffer supplied is returned. If the socket has been configured for in- line reception of out-of-band data (socket option SO_OOBINLINE) and out-of-band data is unread, only out-of-band data will be returned. The application may use the ioctlsocket() SIOCATMARK to determine whether any more out-of-band data remains to be read.
For datagram sockets, data is extracted from the first enqueued datagram, up to the size of the buffer supplied. If the datagram is larger than the buffer supplied, the buffer is filled with the first part of the datagram, the excess data is lost, and recv() returns the error WSAEMSGSIZE.
If no incoming data is available at the socket, the recv() call waits for data to arrive unless the socket is non-blocking. In this case a value of SOCKET_ERROR is returned with the error code set to WSAEWOULDBLOCK. The select() or WSAAsyncSelect() calls may be used to determine when more data arrives.
If the socket is of type SOCK_STREAM and the remote side has shut down the connection gracefully, a recv() will complete immediately with 0 bytes received. If the connection has been reset, a recv() will fail with the error WSAECONNRESET.
Flags may be used to influence the behavior of the function invocation beyond the options specified for the associated socket. That is, the semantics of this function are determined by the socket options and the flags parameter. The latter is constructed by or-ing any of the following values:
Value Meaning MSG_PEEK Peek at the incoming data. The data is copied into the buffer but is not removed from the input queue. MSG_OOB Process out-of-band data (See section 2.2.3 for a discussion of this topic.)
#include <winsock.h> int PASCAL FAR recvfrom ( SOCKET s, char FAR * buf, int len, int flags, struct sockaddr FAR * from, int FAR * fromlen );
For sockets of type SOCK_STREAM, as much information as is currently available up to the size of the buffer supplied is returned. If the socket has been configured for in- line reception of out-of-band data (socket option SO_OOBINLINE) and out-of-band data is unread, only out-of-band data will be returned. The application may use the ioctlsocket() SIOCATMARK to determine whether any more out-of-band data remains to be read. The from and fromlen parameters are ignored for SOCK_STREAM sockets.
For datagram sockets, data is extracted from the first enqueued datagram, up to the size of the buffer supplied. If the datagram is larger than the buffer supplied, the buffer is filled with the first part of the message, the excess data is lost, and recvfrom() returns the error code WSAEMSGSIZE.
If from is non-zero, and the socket is of type SOCK_DGRAM, the network address of the peer which sent the data is copied to the corresponding struct sockaddr. The value pointed to by fromlen is initialized to the size of this structure, and is modified on return to indicate the actual size of the address stored there.
If no incoming data is available at the socket, the recvfrom() call waits for data to arrive unless the socket is non-blocking. In this case a value of SOCKET_ERROR is returned with the error code set to WSAEWOULDBLOCK. The select() or WSAAsyncSelect() calls may be used to determine when more data arrives.
If the socket is of type SOCK_STREAM and the remote side has shut down the connection gracefully, a recvfrom() will complete immediately with 0 bytes received. If the connection has been reset recv() will fail with the error WSAECONNRESET.
Flags may be used to influence the behavior of the function invocation beyond the options specified for the associated socket. That is, the semantics of this function are determined by the socket options and the flags parameter. The latter is constructed by or-ing any of the following values:
Value Meaning MSG_PEEK Peek at the incoming data. The data is copied into the buffer but is not removed from the input queue. MSG_OOB Process out-of-band data (See section 2.2.3 for a discussion of this topic.)
#include <winsock.h> int PASCAL FAR select ( int nfds, fd_set FAR * readfds, fd_set FAR * writefds, fd_set FAR * exceptfds, const struct timeval FAR * timeout );
The parameter readfds identifies those sockets which are to be checked for readability. If the socket is currently listen()ing, it will be marked as readable if an incoming connection request has been received, so that an accept() is guaranteed to complete without blocking. For other sockets, readability means that queued data is available for reading or, for sockets of type SOCK_STREAM, that the virtual socket corresponding to the socket has been closed, so that a recv() or recvfrom() is guaranteed to complete without blocking. If the virtual circuit was closed gracefully, then a recv() will return immediately with 0 bytes read; if the virtual circuit was reset, then a recv() will complete immediately with the error code WSAECONNRESET. The presence of out-of- band data will be checked if the socket option SO_OOBINLINE has been enabled (see setsockopt()).
The parameter writefds identifies those sockets which are to be checked for writability. If a socket is connect()ing (non-blocking), writability means that the connection establishment successfully completed. If the socket is not in the process of connect()ing, writability means that a send() or sendto() will complete without blocking. [It is not specified how long this guarantee can be assumed to be valid, particularly in a multithreaded environment.]
The parameter exceptfds identifies those sockets which are to be checked for the presence of out-of-band data or any exceptional error conditions. Note that out-of-band data will only be reported in this way if the option SO_OOBINLINE is FALSE. For a SOCK_STREAM, the breaking of the connection by the peer or due to KEEPALIVE failure will be indicated as an exception. This specification does not define which other errors will be included. If a socket is connect()ing (non-blocking), failure of the connect attempt is indicated in exceptfds.
Any of readfds, writefds, or exceptfds may be given as NULL if no descriptors are of interest.
Four macros are defined in the header file winsock.h for manipulating the descriptor sets. The variable FD_SETSIZE determines the maximum number of descriptors in a set. (The default value of FD_SETSIZE is 64, which may be modified by #defining FD_SETSIZE to another value before #including winsock.h.) Internally, an fd_set is represented as an array of SOCKETs; the last valid entry is followed by an element set to INVALID_SOCKET. The macros are:
FD_CLR(s, *set) Removes the descriptor s from set. FD_ISSET(s, *set) Nonzero if s is a member of the set, zero otherwise. FD_SET(s, *set) Adds descriptor s to set. FD_ZERO(*set) Initializes the set to the NULL set.The parameter timeout controls how long the select() may take to complete. If timeout is a null pointer, select() will block indefinitely until at least one descriptor meets the specified criteria. Otherwise, timeout points to a struct timeval which specifies the maximum time that select() should wait before returning. If the timeval is initialized to {0, 0}, select() will return immediately; this is used to "poll" the state of the selected sockets. If this is the case, then the select() call is considered nonblocking and the standard assumptions for nonblocking calls apply. For example, the blocking hook must not be called, and the Windows Sockets implementation must not yield.
#include <winsock.h> int PASCAL FAR send ( SOCKET s, const char FAR * buf, int len, int flags );
Note that the successful completion of a send() does not indicate that the data was successfully delivered.
If no buffer space is available within the transport system to hold the data to be transmitted, send() will block unless the socket has been placed in a non-blocking I/O mode. On non-blocking SOCK_STREAM sockets, the number of bytes written may be between 1 and the requested length, depending on buffer availability on both the local and foreign hosts. The select() call may be used to determine when it is possible to send more data.
Flags may be used to influence the behavior of the function invocation beyond the options specified for the associated socket. That is, the semantics of this function are determined by the socket options and the flags parameter. The latter is constructed by or-ing any of the following values:
Value Meaning MSG_DONTROUTE Specifies that the data should not be subject to routing. A Windows Sockets supplier may choose to ignore this flag; see also the discussion of the SO_DONTROUTE option in section 2.4. MSG_OOB Send out-of-band data (SOCK_STREAM only; see also section 2.2.3)
#include <winsock.h> int PASCAL FAR sendto ( SOCKET s, const char FAR * buf, int len, int flags, const struct sockaddr FAR * to, int tolen );
Note that the successful completion of a sendto() does not indicate that the data was successfully delivered.
sendto() is normally used on a SOCK_DGRAM socket to send a datagram to a specific peer socket identified by the to parameter. On a SOCK_STREAM socket, the to and tolen parameters are ignored; in this case the sendto() is equivalent to send().
To send a broadcast (on a SOCK_DGRAM only), the address in the to parameter should be constructed using the special IP address INADDR_BROADCAST (defined in winsock.h) together with the intended port number. It is generally inadvisable for a broadcast datagram to exceed the size at which fragmentation may occur, which implies that the data portion of the datagram (excluding headers) should not exceed 512 bytes.
If no buffer space is available within the transport system to hold the data to be transmitted, sendto() will block unless the socket has been placed in a non-blocking I/O mode. On non-blocking SOCK_STREAM sockets, the number of bytes written may be between 1 and the requested length, depending on buffer availability on both the local and foreign hosts. The select() call may be used to determine when it is possible to send more data.
Flags may be used to influence the behavior of the function invocation beyond the options specified for the associated socket. That is, the semantics of this function are determined by the socket options and the flags parameter. The latter is constructed by or-ing any of the following values:
Value Meaning MSG_DONTROUTE Specifies that the data should not be subject to routing. A Windows Sockets supplier may choose to ignore this flag; see also the discussion of the SO_DONTROUTE option in section 2.4. MSG_OOB Send out-of-band data (SOCK_STREAM only; see also section 2.2.3)
#include <winsock.h> int PASCAL FAR setsockopt ( SOCKET s, int level, int optname, const char FAR * optval, int optlen );
There are two types of socket options: Boolean options that enable or disable a feature or behavior, and options which require an integer value or structure. To enable a Boolean option, optval points to a nonzero integer. To disable the option optval points to an integer equal to zero. optlen should be equal to sizeof(int) for Boolean options. For other options, optval points to the an integer or structure that contains the desired value for the option, and optlen is the length of the integer or structure.
SO_LINGER controls the action taken when unsent data is queued on a socket and a closesocket() is performed. See closesocket() for a description of the way in which the SO_LINGER settings affect the semantics of closesocket(). The application sets the desired behavior by creating a struct linger (pointed to by the optval argument) with the following elements:
struct linger { int l_onoff; int l_linger; }To enable SO_LINGER, the application should set l_onoff to a non-zero value, set l_linger to 0 or the desired timeout (in seconds), and call setsockopt(). To enable SO_DONTLINGER (i.e. disable SO_LINGER) l_onoff should be set to zero and setsockopt() should be called.
By default, a socket may not be bound (see bind()) to a local address which is already in use. On occasions, however, it may be desirable to "re-use" an address in this way. Since every connection is uniquely identified by the combination of local and remote addresses, there is no problem with having two sockets bound to the same local address as long as the remote addresses are different. To inform the Windows Sockets implementation that a bind() on a socket should not be disallowed because the desired address is already in use by another socket, the application should set the SO_REUSEADDR socket option for the socket before issuing the bind(). Note that the option is interpreted only at the time of the bind(): it is therefore unnecessary (but harmless) to set the option on a socket which is not to be bound to an existing address, and setting or resetting the option after the bind() has no effect on this or any other socket.
An application may request that the Windows Sockets implementation enable the use of "keep-alive" packets on TCP connections by turning on the SO_KEEPALIVE socket option. A Windows Sockets implementation need not support the use of keep-alives: if it does, the precise semantics are implementation-specific but should conform to section 4.2.3.6 of RFC 1122: Requirements for Internet Hosts -- Communication Layers. If a connection is dropped as the result of "keep-alives" the error code WSAENETRESET is returned to any calls in progress on the socket, and any subsequent calls will fail with WSAENOTCONN.
The TCP_NODELAY option disables the Nagle algorithm. The Nagle algorithm is used to reduce the number of small packets sent by a host by buffering unacknowledged send data until a full-size packet can be sent. However, for some applications this algorithm can impede performance, and TCP_NODELAY may be used to turn it off. Application writers should not set TCP_NODELAY unless the impact of doing so is well-understood and desired, since setting TCP_NODELAY can have a significant negative impact of network performance. TCP_NODELAY is the only supported socket option which uses level IPPROTO_TCP; all other options use level SOL_SOCKET.
Windows Sockets suppliers are encouraged (but not required) to supply output debug information if the SO_DEBUG option is set by an application. The mechanism for generating the debug information and the form it takes are beyond the scope of this specification.
The following options are supported for setsockopt(). The Type identifies the type of data addressed by optval.
Value Type Meaning SO_BROADCAST BOOL Allow transmission of broadcast messages on the socket. SO_DEBUG BOOL Record debugging information. SO_DONTLINGER BOOL Don't block close waiting for unsent data to be sent. Setting this option is equivalent to setting SO_LINGER with l_onoff set to zero. SO_DONTROUTE BOOL Don't route: send directly to interface. SO_KEEPALIVE BOOL Send keepalives SO_LINGER struct linger Linger on close if unsent data is present FAR * SO_OOBINLINE BOOL Receive out-of-band data in the normal data stream. SO_RCVBUF int Specify buffer size for receives SO_REUSEADDR BOOL Allow the socket to be bound to an address which is already in use. (See bind().) SO_SNDBUF int Specify buffer size for sends. TCP_NODELAY BOOL Disables the Nagle algorithm for send coalescing.BSD options not supported for setsockopt() are:
Value Type Meaning SO_ACCEPTCONN BOOL Socket is listening SO_ERROR int Get error status and clear SO_RCVLOWAT int Receive low water mark SO_RCVTIMEO int Receive timeout SO_SNDLOWAT int Send low water mark SO_SNDTIMEO int Send timeout SO_TYPE int Type of the socket IP_OPTIONS Set options field in IP header.
#include <winsock.h> int PASCAL FAR shutdown ( SOCKET s, int how );
If how is 0, subsequent receives on the socket will be disallowed. This has no effect on the lower protocol layers. For TCP, the TCP window is not changed and incoming data will be accepted (but not acknowledged) until the window is exhausted. For UDP, incoming datagrams are accepted and queued. In no case will an ICMP error packet be generated.
If how is 1, subsequent sends are disallowed. For TCP sockets, a FIN will be sent.
Setting how to 2 disables both sends and receives as described above.
Note that shutdown() does not close the socket, and resources attached to the socket will not be freed until closesocket() is invoked.
An application should not rely on being able to re-use a socket after it has been shut down. In particular, a Windows Sockets implementation is not required to support the use of connect() on such a socket.
#include <winsock.h> SOCKET PASCAL FAR socket ( int af, int type, int protocol );
Only a single protocol exists to support a particular socket type using a given address format. However, the address family may be given as AF_UNSPEC (unspecified), in which case the protocol parameter must be specified. The protocol number to use is particular to the "communication domain'' in which communication is to take place.
The following type specifications are supported:
Type Explanation SOCK_STREAM Provides sequenced, reliable, two-way, connection-based byte streams with an out-of-band data transmission mechanism. Uses TCP for the Internet address family. SOCK_DGRAM Supports datagrams, which are connectionless, unreliable buffers of a fixed (typically small) maximum length. Uses UDP for the Internet address family.Sockets of type SOCK_STREAM are full-duplex byte streams. A stream socket must be in a connected state before any data may be sent or received on it. A connection to another socket is created with a connect() call. Once connected, data may be transferred using send() and recv() calls. When a session has been completed, a closesocket() must be performed. Out-of-band data may also be transmitted as described in send() and received as described in recv().
The communications protocols used to implement a SOCK_STREAM ensure that data is not lost or duplicated. If data for which the peer protocol has buffer space cannot be successfully transmitted within a reasonable length of time, the connection is considered broken and subsequent calls will fail with the error code set to WSAETIMEDOUT.
SOCK_DGRAM sockets allow sending and receiving of datagrams to and from arbitrary peers using sendto() and recvfrom(). If such a socket is connect()ed to a specific peer, datagrams may be send to that peer send() and may be received from (only) this peer using recv().
#include <winsock.h> struct hostent FAR * PASCAL FAR gethostbyaddr ( const char FAR * addr, int len, int type );
struct hostent { char FAR * h_name; char FAR * FAR * h_aliases; short h_addrtype; short h_length; char FAR * FAR * h_addr_list; };The members of this structure are:
Element Usage h_name Official name of the host (PC). h_aliases A NULL-terminated array of alternate names. h_addrtype The type of address being returned; for Windows Sockets this is always PF_INET. h_length The length, in bytes, of each address; for PF_INET, this is always 4. h_addr_list A NULL-terminated list of addresses for the host. Addresses are returned in network byte order.The macro h_addr is defined to be h_addr_list[0] for compatibility with older software.
The pointer which is returned points to a structure which is allocated by the Windows Sockets implementation. The application must never attempt to modify this structure or to free any of its components. Furthermore, only one copy of this structure is allocated per thread, and so the application should copy any information which it needs before issuing any other Windows Sockets API calls.
#include <winsock.h> struct hostent FAR * PASCAL FAR gethostbyname ( const char FAR * name );
The pointer which is returned points to a structure which is allocated by the Windows Sockets implementation. The application must never attempt to modify this structure or to free any of its components. Furthermore, only one copy of this structure is allocated per thread, and so the application should copy any information which it needs before issuing any other Windows Sockets API calls.
A gethostbyname() implementation must not resolve IP address strings passed to it. Such a request should be treated exactly as if an unknown host name were passed. An application with an IP address string to resolve should use inet_addr() to convert the string to an IP address, then gethostbyaddr() to obtain the hostent structure.
#include <winsock.h> int PASCAL FAR gethostname ( char FAR * name, int namelen );
#include <winsock.h> struct protoent FAR * PASCAL FAR getprotobyname ( const char FAR * name );
struct protoent { char FAR * p_name; char FAR * FAR * p_aliases; short p_proto; };The members of this structure are:
Element Usage p_name Official name of the protocol. p_aliases A NULL-terminated array of alternate names. p_proto The protocol number, in host byte order.The pointer which is returned points to a structure which is allocated by the Windows Sockets library. The application must never attempt to modify this structure or to free any of its components. Furthermore only one copy of this structure is allocated per thread, and so the application should copy any information which it needs before issuing any other Windows Sockets API calls.
#include <winsock.h> struct protoent FAR * PASCAL FAR getprotobynumber ( int number );
The pointer which is returned points to a structure which is allocated by the Windows Sockets implementation. The application must never attempt to modify this structure or to free any of its components. Furthermore, only one copy of this structure is allocated per thread, and so the application should copy any information which it needs before issuing any other Windows Sockets API calls.
#include <winsock.h> struct servent FAR * PASCAL FAR getservbyname ( const char FAR * name, const char FAR * proto );
struct servent { char FAR * s_name; char FAR * FAR * s_aliases; short s_port; char FAR * s_proto; };The members of this structure are:
Element Usage s_name Official name of the service. s_aliases A NULL-terminated array of alternate names. s_port The port number at which the service may be contacted. Port numbers are returned in network byte order. s_proto The name of the protocol to use when contacting the service.The pointer which is returned points to a structure which is allocated by the Windows Sockets library. The application must never attempt to modify this structure or to free any of its components. Furthermore only one copy of this structure is allocated per thread, and so the application should copy any information which it needs before issuing any other Windows Sockets API calls.
#include <winsock.h> struct servent FAR * PASCAL FAR getservbyport ( int port, const char FAR * proto );
The pointer which is returned points to a structure which is allocated by the Windows Sockets implementation. The application must never attempt to modify this structure or to free any of its components. Furthermore, only one copy of this structure is allocated per thread, and so the application should copy any information which it needs before issuing any other Windows Sockets API calls.
#include <winsock.h> HANDLE PASCAL FAR WSAAsyncGetHostByAddr ( HWND hWnd, unsigned int wMsg, const char FAR * addr, int len, int type, char FAR * buf, int buflen );
When the asynchronous operation is complete the application's window hWnd receives message wMsg. The wParam argument contains the asynchronous task handle as returned by the original function call. The high 16 bits of lParam contain any error code. The error code may be any error as defined in winsock.h. An error code of zero indicates successful completion of the asynchronous operation. On successful completion, the buffer supplied to the original function call contains a hostent structure. To access the elements of this structure, the original buffer address should be cast to a hostent structure pointer and accessed as appropriate.
Note that if the error code is WSAENOBUFS, it indicates that the size of the buffer specified by buflen in the original call was too small to contain all the resultant information. In this case, the low 16 bits of lParam contain the size of buffer required to supply ALL the requisite information. If the application decides that the partial data is inadequate, it may reissue the WSAAsyncGetHostByAddr() function call with a buffer large enough to receive all the desired information (i.e. no smaller than the low 16 bits of lParam).
The error code and buffer length should be extracted from the lParam using the macros WSAGETASYNCERROR and WSAGETASYNCBUFLEN, defined in winsock.h as:
#define WSAGETASYNCERROR(lParam) HIWORD(lParam) #define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam)The use of these macros will maximize the portability of the source code for the application.
If the operation was successfully initiated, WSAAsyncGetHostByAddr() returns a nonzero value of type HANDLE which is the asynchronous task handle for the request. This value can be used in two ways. It can be used to cancel the operation using WSACancelAsyncRequest(). It can also be used to match up asynchronous operations and completion messages, by examining the wParam message argument.
If the asynchronous operation could not be initiated, WSAAsyncGetHostByAddr() returns a zero value, and a specific error number may be retrieved by calling WSAGetLastError().
Windows Sockets suppliers should use the WSAMAKEASYNCREPLY macro when constructing the lParam in the message.
#include <winsock.h> HANDLE PASCAL FAR WSAAsyncGetHostByName ( HWND hWnd, unsigned int wMsg, const char FAR * name, char FAR * buf, int buflen );
When the asynchronous operation is complete the application's window hWnd receives message wMsg. The wParam argument contains the asynchronous task handle as returned by the original function call. The high 16 bits of lParam contain any error code. The error code may be any error as defined in winsock.h. An error code of zero indicates successful completion of the asynchronous operation. On successful completion, the buffer supplied to the original function call contains a hostent structure. To access the elements of this structure, the original buffer address should be cast to a hostent structure pointer and accessed as appropriate.
Note that if the error code is WSAENOBUFS, it indicates that the size of the buffer specified by buflen in the original call was too small to contain all the resultant information. In this case, the low 16 bits of lParam contain the size of buffer required to supply ALL the requisite information. If the application decides that the partial data is inadequate, it may reissue the WSAAsyncGetHostByName() function call with a buffer large enough to receive all the desired information (i.e. no smaller than the low 16 bits of lParam).
The error code and buffer length should be extracted from the lParam using the macros WSAGETASYNCERROR and WSAGETASYNCBUFLEN, defined in winsock.h as:
#define WSAGETASYNCERROR(lParam) HIWORD(lParam) #define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam)The use of these macros will maximize the portability of the source code for the application.
If the operation was successfully initiated, WSAAsyncGetHostByName() returns a nonzero value of type HANDLE which is the asynchronous task handle for the request. This value can be used in two ways. It can be used to cancel the operation using WSACancelAsyncRequest(). It can also be used to match up asynchronous operations and completion messages, by examining the wParam message argument.
If the asynchronous operation could not be initiated, WSAAsyncGetHostByName() returns a zero value, and a specific error number may be retrieved by calling WSAGetLastError().
Windows Sockets suppliers should use the WSAMAKEASYNCREPLY macro when constructing the lParam in the message.
#include <winsock.h> HANDLE PASCAL FAR WSAAsyncGetProtoByName ( HWND hWnd, unsigned int wMsg, const char FAR * name, char FAR * buf, int buflen );
When the asynchronous operation is complete the application's window hWnd receives message wMsg. The wParam argument contains the asynchronous task handle as returned by the original function call. The high 16 bits of lParam contain any error code. The error code may be any error as defined in winsock.h. An error code of zero indicates successful completion of the asynchronous operation. On successful completion, the buffer supplied to the original function call contains a protoent structure. To access the elements of this structure, the original buffer address should be cast to a protoent structure pointer and accessed as appropriate.
Note that if the error code is WSAENOBUFS, it indicates that the size of the buffer specified by buflen in the original call was too small to contain all the resultant information. In this case, the low 16 bits of lParam contain the size of buffer required to supply ALL the requisite information. If the application decides that the partial data is inadequate, it may reissue the WSAAsyncGetProtoByName() function call with a buffer large enough to receive all the desired information (i.e. no smaller than the low 16 bits of lParam).
The error code and buffer length should be extracted from the lParam using the macros WSAGETASYNCERROR and WSAGETASYNCBUFLEN, defined in winsock.h as:
#define WSAGETASYNCERROR(lParam) HIWORD(lParam) #define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam)The use of these macros will maximize the portability of the source code for the application.
If the operation was successfully initiated, WSAAsyncGetProtoByName() returns a nonzero value of type HANDLE which is the asynchronous task handle for the request. This value can be used in two ways. It can be used to cancel the operation using WSACancelAsyncRequest(). It can also be used to match up asynchronous operations and completion messages, by examining the wParam message argument.
If the asynchronous operation could not be initiated, WSAAsyncGetProtoByName() returns a zero value, and a specific error number may be retrieved by calling WSAGetLastError().
Windows Sockets suppliers should use the WSAMAKEASYNCREPLY macro when constructing the lParam in the message.
#include <winsock.h> HANDLE PASCAL FAR WSAAsyncGetProtoByNumber ( HWND hWnd, unsigned int wMsg, int number, char FAR * buf, int buflen );
When the asynchronous operation is complete the application's window hWnd receives message wMsg. The wParam argument contains the asynchronous task handle as returned by the original function call. The high 16 bits of lParam contain any error code. The error code may be any error as defined in winsock.h. An error code of zero indicates successful completion of the asynchronous operation. On successful completion, the buffer supplied to the original function call contains a protoent structure. To access the elements of this structure, the original buffer address should be cast to a protoent structure pointer and accessed as appropriate.
Note that if the error code is WSAENOBUFS, it indicates that the size of the buffer specified by buflen in the original call was too small to contain all the resultant information. In this case, the low 16 bits of lParam contain the size of buffer required to supply ALL the requisite information. If the application decides that the partial data is inadequate, it may reissue the WSAAsyncGetProtoByNumber() function call with a buffer large enough to receive all the desired information (i.e. no smaller than the low 16 bits of lParam).
The error code and buffer length should be extracted from the lParam using the macros WSAGETASYNCERROR and WSAGETASYNCBUFLEN, defined in winsock.h as:
#define WSAGETASYNCERROR(lParam) HIWORD(lParam) #define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam)The use of these macros will maximize the portability of the source code for the application.
If the operation was successfully initiated, WSAAsyncGetProtoByNumber() returns a nonzero value of type HANDLE which is the asynchronous task handle for the request. This value can be used in two ways. It can be used to cancel the operation using WSACancelAsyncRequest(). It can also be used to match up asynchronous operations and completion messages, by examining the wParam message argument.
If the asynchronous operation could not be initiated, WSAAsyncGetProtoByNumber() returns a zero value, and a specific error number may be retrieved by calling WSAGetLastError().
Windows Sockets suppliers should use the WSAMAKEASYNCREPLY macro when constructing the lParam in the message.
#include <winsock.h> HANDLE PASCAL FAR WSAAsyncGetServByName ( HWND hWnd, unsigned int wMsg, const char FAR * name, const char FAR * proto, char FAR * buf, int buflen );
When the asynchronous operation is complete the application's window hWnd receives message wMsg. The wParam argument contains the asynchronous task handle as returned by the original function call. The high 16 bits of lParam contain any error code. The error code may be any error as defined in winsock.h. An error code of zero indicates successful completion of the asynchronous operation. On successful completion, the buffer supplied to the original function call contains a hostent structure. To access the elements of this structure, the original buffer address should be cast to a hostent structure pointer and accessed as appropriate.
Note that if the error code is WSAENOBUFS, it indicates that the size of the buffer specified by buflen in the original call was too small to contain all the resultant information. In this case, the low 16 bits of lParam contain the size of buffer required to supply ALL the requisite information. If the application decides that the partial data is inadequate, it may reissue the WSAAsyncGetServByName() function call with a buffer large enough to receive all the desired information (i.e. no smaller than the low 16 bits of lParam).
The error code and buffer length should be extracted from the lParam using the macros WSAGETASYNCERROR and WSAGETASYNCBUFLEN, defined in winsock.h as:
#define WSAGETASYNCERROR(lParam) HIWORD(lParam) #define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam)The use of these macros will maximize the portability of the source code for the application.
If the operation was successfully initiated, WSAAsyncGetServByName() returns a nonzero value of type HANDLE which is the asynchronous task handle for the request. This value can be used in two ways. It can be used to cancel the operation using WSACancelAsyncRequest(). It can also be used to match up asynchronous operations and completion messages, by examining the wParam message argument.
If the asynchronous operation could not be initiated, WSAAsyncServByName() returns a zero value, and a specific error number may be retrieved by calling WSAGetLastError().
Windows Sockets suppliers should use the WSAMAKEASYNCREPLY macro when constructing the lParam in the message.
#include <winsock.h> HANDLE PASCAL FAR WSAAsyncGetServByPort ( HWND hWnd, unsigned int wMsg, int port, const char FAR * proto, char FAR * buf, int buflen );
When the asynchronous operation is complete the application's window hWnd receives message wMsg. The wParam argument contains the asynchronous task handle as returned by the original function call. The high 16 bits of lParam contain any error code. The error code may be any error as defined in winsock.h. An error code of zero indicates successful completion of the asynchronous operation. On successful completion, the buffer supplied to the original function call contains a servent structure. To access the elements of this structure, the original buffer address should be cast to a servent structure pointer and accessed as appropriate.
Note that if the error code is WSAENOBUFS, it indicates that the size of the buffer specified by buflen in the original call was too small to contain all the resultant information. In this case, the low 16 bits of lParam contain the size of buffer required to supply ALL the requisite information. If the application decides that the partial data is inadequate, it may reissue the WSAAsyncGetServByPort() function call with a buffer large enough to receive all the desired information (i.e. no smaller than the low 16 bits of lParam).
The error code and buffer length should be extracted from the lParam using the macros WSAGETASYNCERROR and WSAGETASYNCBUFLEN, defined in winsock.h as:
#define WSAGETASYNCERROR(lParam) HIWORD(lParam) #define WSAGETASYNCBUFLEN(lParam) LOWORD(lParam)The use of these macros will maximize the portability of the source code for the application.
If the operation was successfully initiated, WSAAsyncGetServByPort() returns a nonzero value of type HANDLE which is the asynchronous task handle for the request. This value can be used in two ways. It can be used to cancel the operation using WSACancelAsyncRequest(). It can also be used to match up asynchronous operations and completion messages, by examining the wParam message argument.
If the asynchronous operation could not be initiated, WSAAsyncGetServByPort() returns a zero value, and a specific error number may be retrieved by calling WSAGetLastError().
Windows Sockets suppliers should use the WSAMAKEASYNCREPLY macro when constructing the lParam in the message.
#include <winsock.h> int PASCAL FAR WSAAsyncSelect ( SOCKET s, HWND hWnd, unsigned int wMsg, long lEvent );
This function automatically sets socket s to non-blocking mode.
The lEvent parameter is constructed by or'ing any of the values specified in the following list.
Value Meaning FD_READ Want to receive notification of readiness for reading FD_WRITE Want to receive notification of readiness for writing FD_OOB Want to receive notification of the arrival of out-of-band data FD_ACCEPT Want to receive notification of incoming connections FD_CONNECT Want to receive notification of completed connection FD_CLOSE Want to receive notification of socket closureIssuing a WSAAsyncSelect() for a socket cancels any previous WSAAsyncSelect() for the same socket. For example, to receive notification for both reading and writing, the application must call WSAAsyncSelect() with both FD_READ and FD_WRITE, as follows:
rc = WSAAsyncSelect(s, hWnd, wMsg, FD_READ|FD_WRITE);It is not possible to specify different messages for different events. The following code will not work; the second call will cancel the effects of the first, and only FD_WRITE events will be reported with message wMsg2:
rc = WSAAsyncSelect(s, hWnd, wMsg1, FD_READ); rc = WSAAsyncSelect(s, hWnd, wMsg2, FD_WRITE);To cancel all notification - i.e., to indicate that the Windows Sockets implementation should send no further messages related to network events on the socket - lEvent should be set to zero.
rc = WSAAsyncSelect(s, hWnd, 0, 0);Although in this instance WSAAsyncSelect() immediately disables event message posting for the socket, it is possible that messages may be waiting in the application's message queue. The application must therefore be prepared to receive network event messages even after cancellation. Closing a socket with closesocket() also cancels WSAAsyncSelect() message sending, but the same caveat about messages in the queue prior to the closesocket() still applies.
Since an accept()'ed socket has the same properties as the listening socket used to accept it, any WSAAsyncSelect() events set for the listening socket apply to the accepted socket. For example, if a listening socket has WSAAsyncSelect() events FD_ACCEPT, FD_READ, and FD_WRITE, then any socket accepted on that listening socket will also have FD_ACCEPT, FD_READ, and FD_WRITE events with the same wMsg value used for messages. If a different wMsg or events are desired, the application should call WSAAsyncSelect(), passing the accepted socket and the desired new information. [7]
When one of the nominated network events occurs on the specified socket s, the application's window hWnd receives message wMsg. The wParam argument identifies the socket on which a network event has occurred. The low word of lParam specifies the network event that has occurred. The high word of lParam contains any error code. The error code be any error as defined in winsock.h.
The error and event codes may be extracted from the lParam using the macros WSAGETSELECTERROR and WSAGETSELECTEVENT, defined in winsock.h as:
#define WSAGETSELECTERROR(lParam) HIWORD(lParam) #define WSAGETSELECTEVENT(lParam) LOWORD(lParam)The use of these macros will maximize the portability of the source code for the application.
The possible network event codes which may be returned are as follows:
Value Meaning FD_READ Socket s ready for reading FD_WRITE Socket s ready for writing FD_OOB Out-of-band data ready for reading on socket s. FD_ACCEPT Socket s ready for accepting a new incoming connection FD_CONNECT Connection on socket s completed FD_CLOSE Connection identified by socket s has been closed
As in the case of the select() function, WSAAsyncSelect() will frequently be used to determine when a data transfer operation (send() or recv()) can be issued with the expectation of immediate success. Nevertheless, a robust application must be prepared for the possibility that it may receive a message and issue a Windows Sockets API call which returns WSAEWOULDBLOCK immediately. For example, the following sequence of events is possible:
Other sequences are possible.
The Windows Sockets DLL will not continually flood an application with messages for a particular network event. Having successfully posted notification of a particular event to an application window, no further message(s) for that network event will be posted to the application window until the application makes the function call which implicitly reenables notification of that network event.
Event Re-enabling function FD_READ recv() or recvfrom() FD_WRITE send() or sendto() FD_OOB recv() FD_ACCEPT accept() FD_CONNECT NONE FD_CLOSE NONEAny call to the reenabling routine, even one which fails, results in reenabling of message posting for the relevant event.
For FD_READ, FD_OOB, and FD_ACCEPT events, message posting is "level-triggered." This means that if the reenabling routine is called and the relevant event is still valid after the call, a WSAAsyncSelect() message is posted to the application. This allows an application to be event-driven and not concern itself with the amount of data that arrives at any one time. Consider the following sequence:
With these semantics, an application need not read all available data in response to an FD_READ message--a single recv() in response to each FD_READ message is appropriate. If an application issues multiple recv() calls in response to a single FD_READ, it may receive multiple FD_READ messages. Such an application may wish to disable FD_READ messages before starting the recv() calls by calling WSAAsyncSelect() with the FD_READ event not set.
If an event is true when the application initially calls WSAAsyncSelect() or when the reenabling function is called, then a message is posted as appropriate. For example, if an application calls listen(), a connect attempt is made, then the application calls WSAAsyncSelect() specifying that it wants to receive FD_ACCEPT messages for the socket, the Windows Sockets implementation posts an FD_ACCEPT message immediately.
The FD_WRITE event is handled slightly differently. An FD_WRITE message is posted when a socket is first connected with connect() or accepted with accept(), and then after a send() or sendto() fails with WSAEWOULDBLOCK and buffer space becomes available. Therefore, an application can assume that sends are possible starting from the first FD_WRITE message and lasting until a send returns WSAEWOULDBLOCK. After such a failure the application will be notified that sends are again possible with an FD_WRITE message.
The FD_OOB event is used only when a socket is configured to receive out-of-band data separately. If the socket is configured to receive out-of-band data in-line, the out-of- band (expedited) data is treated as normal data and the application should register an interest in, and will receive, FD_READ events, not FD_OOB events. An application may set or inspect the way in which out-of-band data is to be handled by using setsockopt() or getsockopt() for the SO_OOBINLINE option.
The error code in an FD_CLOSE message indicates whether the socket close was graceful or abortive. If the error code is 0, then the close was graceful; if the error code is WSAECONNRESET, then the socket's virtual socket was reset. This only applies to sockets of type SOCK_STREAM.
The FD_CLOSE message is posted when a close indication is received for the virtual circuit corresponding to the socket. In TCP terms, this means that the FD_CLOSE is posted when the connection goes into the FIN WAIT or CLOSE WAIT states. This results from the remote end performing a shutdown() on the send side or a closesocket().
Please note your application will receive ONLY an FD_CLOSE message to indicate closure of a virtual circuit. It will NOT receive an FD_READ message to indicate this condition.
Error Code Meaning WSAEADDRINUSE The specified address is already in use. WSAEADDRNOTAVAIL The specified address is not available from the local machine. WSAEAFNOSUPPORT Addresses in the specified family cannot be used with this socket. WSAECONNREFUSED The attempt to connect was forcefully rejected. WSAEDESTADDRREQ A destination address is required. WSAEFAULT The namelen argument is incorrect. WSAEINVAL The socket is already bound to an address. WSAEISCONN The socket is already connected. WSAEMFILE No more file descriptors are available. WSAENETUNREACH The network can't be reached from this host at this time. WSAENOBUFS No buffer space is available. The socket cannot be connected. WSAENOTCONN The socket is not connected. WSAENOTSOCK The descriptor is a file, not a socket. WSAETIMEDOUT Attempt to connect timed out without establishing a connection.
Error Code Meaning WSAENETDOWN The Windows Sockets implementation has detected that the network subsystem has failed. WSAECONNRESET The connection was reset by the remote side. WSAECONNABORTED The connection was aborted due to timeout or other failure.
Error Code Meaning WSAENETDOWN The Windows Sockets implementation has detected that the network subsystem has failed.
Windows Sockets suppliers should use the WSAMAKESELECTREPLY macro when constructing the lParam in the message.
When a socket is closed, the Windows Sockets Supplier should purge any messages remaining for posting to the application window. However the application must be prepared to receive, and discard, any messages which may have been posted prior to the closesocket().
#include <winsock.h> int PASCAL FAR WSACancelAsyncRequest ( HANDLE hAsyncTaskHandle );
#include <winsock.h> int PASCAL FAR WSACancelBlockingCall ( void );
In each case, the original blocking call will terminate as soon as possible with the error WSAEINTR. (In (1), the termination will not take place until Windows message scheduling has caused control to revert to the blocking routine in Windows Sockets. In (2), the blocking call will be terminated as soon as the blocking hook function completes.)
In the case of a blocking connect() operation, the Windows Sockets implementation will terminate the blocking call as soon as possible, but it may not be possible for the socket resources to be released until the connection has completed (and then been reset) or timed out. This is likely to be noticeable only if the application immediately tries to open a new socket (if no sockets are available), or to connect() to the same peer.
Cancelling an accept() or a select() call does not adversely impact the sockets passed to these calls. Only the particular call fails; any operation that was legal before the cancel is legal after the cancel, and the state of the socket is not affected in any way.
Cancelling any operation other than accept() and select() can leave the socket in an indeterminate state. If an application cancels a blocking operation on a socket, the only operation that the application can depend on being able to perform on the socket is a call to closesocket(), although other operations may work on some Windows Sockets implementations. If an application desires maximum portability, it must be careful not to depend on performing operations after a cancel. An application may reset the connection by setting the timeout on SO_LINGER to 0.
If a cancel operation compromised the integrity of a SOCK_STREAM's data stream in any way, the Windows Sockets implementation must reset the connection and fail all future operations other than closesocket() with WSAECONNABORTED.
#include <winsock.h> int PASCAL FAR WSACleanup ( void );
There must be a call to WSACleanup() for every call to WSAStartup() made by a task. Only the final WSACleanup() for that task does the actual cleanup; the preceding calls simply decrement an internal reference count in the Windows Sockets DLL. A naive application may ensure that WSACleanup() was called enough times by calling WSACleanup() in a loop until it returns WSANOTINITIALISED.
A Windows Sockets implementation must be prepared to deal with an application which terminates without invoking WSACleanup() - for example, as a result of an error.
In a multithreaded environment, WSACleanup() terminates Windows Sockets operations for all threads.
A Windows Sockets implementation must ensure that WSACleanup() leaves things in a state in which the application can invoke WSAStartup() to re-establish Windows Sockets usage.
#include <winsock.h> int PASCAL FAR WSAGetLastError ( void );
Note that in a nonpreemptive Windows environment WSAGetLastError() is used to retrieve only Windows Sockets API errors. In a preemptive environment, WSAGetLastError() will invoke GetLastError(), which is used to retrieve the error status for all Win32 API functions on a per-thread basis. For portability, an application should use WSAGetLastError() immediately after the Windows Sockets API function which failed.
#include <winsock.h> BOOL PASCAL FAR WSAIsBlocking ( void );
#include <winsock.h> FARPROC PASCAL FAR WSASetBlockingHook ( FARPROC lpBlockFunc );
A Windows Sockets implementation includes a default mechanism by which blocking socket functions are implemented. The function WSASetBlockingHook() gives the application the ability to execute its own function at "blocking" time in place of the default function.
When an application invokes a blocking Windows Sockets API operation, the Windows Sockets implementation initiates the operation and then enters a loop which is similar to the following pseudocode:
for(;;) { /* flush messages for good user response */ while(BlockingHook()) ; /* check for WSACancelBlockingCall() */ if(operation_cancelled()) break; /* check to see if operation completed */ if(operation_complete()) break; /* normal completion */ }Note that Windows Sockets implementations may perform the above steps in a different order; for example, the check for operation complete may occur before calling the blocking hook. The default BlockingHook() function is equivalent to:
BOOL DefaultBlockingHook(void) { MSG msg; BOOL ret; /* get the next message if any */ ret = (BOOL)PeekMessage(&msg,NULL,0,0,PM_REMOVE); /* if we got one, process it */ if (ret) { TranslateMessage(&msg); DispatchMessage(&msg); } /* TRUE if we got a message */ return ret; }The WSASetBlockingHook() function is provided to support those applications which require more complex message processing - for example, those employing the MDI (multiple document interface) model. It is not intended as a mechanism for performing general applications functions. In particular, the only Windows Sockets API function which may be issued from a custom blocking hook function is WSACancelBlockingCall(), which will cause the blocking loop to terminate.
This function must be implemented on a per-task basis for non-multithreaded versions of Windows and on a per-thread basis for multithreaded versions of Windows such as Windows NT. It thus provides for a particular task or thread to replace the blocking mechanism without affecting other tasks or threads.
In multithreaded versions of Windows, there is no default blocking hook--blocking calls block the thread that makes the call. However, an application may install a specific blocking hook by calling WSASetBlockingHook(). This allows easy portability of applications that depend on the blocking hook behavior.
#include <winsock.h> void PASCAL FAR WSASetLastError ( int iError );
#include <winsock.h> int PASCAL FAR WSAStartup ( WORD wVersionRequested, LPWSADATA lpWSAData );
In order to support future Windows Sockets implementations and applications which may have functionality differences from Windows Sockets 1.1, a negotiation takes place in WSAStartup(). The caller of WSAStartup() and the Windows Sockets DLL indicate to each other the highest version that they can support, and each confirms that the other's highest version is acceptable. Upon entry to WSAStartup(), the Windows Sockets DLL examines the version requested by the application. If this version is higher than the lowest version supported by the DLL, the call succeeds and the DLL returns in wHighVersion the highest version it supports and in wVersion the minimum of its high version and wVersionRequested. The Windows Sockets DLL then assumes that the application will use wVersion. If the wVersion field of the WSADATA structure is unacceptable to the caller, it should call WSACleanup() and either search for another Windows Sockets DLL or fail to initialize.
This negotiation allows both a Windows Sockets DLL and a Windows Sockets application to support a range of Windows Sockets versions. An application can successfully utilize a Windows Sockets DLL if there is any overlap in the version ranges. The following chart gives examples of how WSAStartup() works in conjunction with different application and Windows Sockets DLL versions:
App DLL wVersion wVersion wHighVersion End Result versions versions Requested 1.1 1.1 1.1 1.1 1.1 use 1.1 1.0, 1.1 1.0 1.1 1.0 1.0 use 1.0 1.0 1.0, 1.1 1.0 1.0 1.1 use 1.0 1.1 1.0, 1.1 1.1 1.1 1.1 use 1.1 1.1 1.0 1.1 1.0 1.0 Application fails 1.0 1.1 1.0 --- --- WSAVERNOTSUPPORTED 1.0, 1.1 1.0, 1.1 1.1 1.1 1.1 use 1.1 1.1, 2.0 1.1 2.0 1.1 1.1 use 1.1 2.0 1.1 2.0 1.1 1.1 Application failsThe following code fragment demonstrates how an application which supports only version 1.1 of Windows Sockets makes a WSAStartup() call:
WORD wVersionRequested; WSADATA wsaData; int err; wVersionRequested = MAKEWORD( 1, 1 ); err = WSAStartup( wVersionRequested, &wsaData ); if ( err != 0 ) { /* Tell the user that we couldn't find a useable */ /* winsock.dll. */ return; } /* Confirm that the Windows Sockets DLL supports 1.1.*/ /* Note that if the DLL supports versions greater */ /* than 1.1 in addition to 1.1, it will still return */ /* 1.1 in wVersion since that is the version we */ /* requested. */ if ( LOBYTE( wsaData.wVersion ) != 1 || HIBYTE( wsaData.wVersion ) != 1 ) { /* Tell the user that we couldn't find a useable */ /* winsock.dll. */ WSACleanup( ); return; } /* The Windows Sockets DLL is acceptable. Proceed. */And this code fragment demonstrates how a Windows Sockets DLL which supports only version 1.1 performs the WSAStartup() negotiation:
/* Make sure that the version requested is >= 1.1. */ /* The low byte is the major version and the high */ /* byte is the minor version. */ if ( LOBYTE( wVersionRequested ) < 1 || ( LOBYTE( wVersionRequested ) == 1 && HIBYTE( wVersionRequested ) < 1 ) { return WSAVERNOTSUPPORTED; } /* Since we only support 1.1, set both wVersion and */ /* wHighVersion to 1.1. */ lpWsaData->wVersion = MAKEWORD( 1, 1 ); lpWsaData->wHighVersion = MAKEWORD( 1, 1 );Once an application or DLL has made a successful WSAStartup() call, it may proceed to make other Windows Sockets API calls as needed. When it has finished using the services of the Windows Sockets DLL, the application or DLL must call WSACleanup() in order to allow the Windows Sockets DLL to free any resources for the application.
Details of the actual Windows Sockets implementation are described in the WSAData structure defined as follows:
struct WSAData { WORD wVersion; WORD wHighVersion; char szDescription[WSADESCRIPTION_LEN+1]; char szSystemStatus[WSASYSSTATUS_LEN+1]; unsigned short iMaxSockets; unsigned short iMaxUdpDg; char FAR * lpVendorInfo; };The members of this structure are:
An application or DLL may call WSAStartup() more than once if it needs to obtain the WSAData structure information more than once. However, the wVersionRequired parameter is assumed to be the same on all calls to WSAStartup(); that is, an application or DLL cannot change the version of Windows Sockets it expects after the initial call to WSAStartup().
There must be one WSACleanup() call corresponding to every WSAStartup() call to allow third-party DLLs to make use of a Windows Sockets DLL on behalf of an application. This means, for example, that if an application calls WSAStartup() three times, it must call WSACleanup() three times. The first two calls to WSACleanup() do nothing except decrement an internal counter; the final WSACleanup() call for the task does all necessary resource deallocation for the task.
Further issues are discussed in the notes for WSACleanup().
WSAVERNOTSUPPORTED The version of Windows Sockets API support requested is not provided by this particular Windows Sockets implementation.
#include <winsock.h> int PASCAL FAR WSAUnhookBlockingHook ( void );
WSAUnhookBlockingHook() will always install the default mechanism, not the previous mechanism. If an application wish to nest blocking hooks - i.e. to establish a temporary blocking hook function and then revert to the previous mechanism (whether the default or one established by an earlier WSASetBlockingHook()) - it must save and restore the value returned by WSASetBlockingHook(); it cannot use WSAUnhookBlockingHook().
In multithreaded versions of Windows such as Windows NT, there is no default blocking hook. Calling WSAUnhookBlockingHook() disables any blocking hook installed by the application and any blocking calls made block the thread which made the call.