Windows SocketsThis document may be freely redistributed in any form, electronic or otherwise, provided that it is distributed in its entirety and that the copyright and this notice are included. Comments or questions may be submitted via electronic mail to WinSock@MailBag.Intel.Com. Requests to be added to the Windows Sockets mailing list should be addressed to MajorDomo@MailBag.Intel.Com. This specification, archives of the mailing list, and other information on Windows Sockets are available via anonymous FTP from the host SunSite.UNC.Edu, directory /pub/micro/pc-stuff/ms-windows/winsock. Questions about products conforming to this specification should be addressed to the vendors of the products.
The authors would like to thank their companies for allowing them the time and resources to make this specification possible: JSB Corporation, Microdyne Corporation, FTP Software, Sun Microsystems, and Microsoft Corporation.
Special thanks should also be extended to the other efforts contributing to the success of Windows Sockets. The original draft was heavily influenced by existing specifications offered and detailed by JSB Corporation and NetManage, Inc. The "version 1.0 debate" hosted by Microsoft in Seattle allowed many of the members of the working group to hash out final details for 1.0 vis-a-vis.
Sun Microsystems was kind enough to allow first time implementors to "plug and play" beta software during the first Windows Sock-A-Thon of Windows Sockets applications and implementations at Interop Fall '92. Microsoft has shared WSAT (the Windows Sockets API Tester) with other Windows Sockets implementors as a standard Windows Sockets test suite to aid in testing their implementations. Finally, Sun Microsystems and FTP Software plan to host the Windows Sock-A-Thon II in Boston February '93.
Without the contributions of the individuals and corporations involved in the working group, Windows Sockets would never have been as thoroughly reviewed and completed as quickly. In just one year, several competitors in the networking business developed a useful specification with something to show for it! Many thanks to all which participated, either in person or on e-mail to the Windows Sockets effort. The authors would like to thank everyone who participated in any way, and apologize in advance for anyone we have omitted.
List of contributors:
Martin Hall (Chairman) JSB Corporation martinh@jsbus.com Mark Towfiq (Coordinator) Microdyne Corporation towfiq@microdyne.com Geoff Arnold (Editor 1.0) Sun Microsystems geoff@east.sun.com David Treadwell (Editor 1.1) Microsoft Corporation davidtr@microsoft.com Henry Sanders Microsoft Corporation henrysa@microsoft.comJ. Allard Microsoft Corporation jallard@microsoft.com Chris Arap-Bologna Distinct chris@distinct.com Larry Backman FTP Software backman@ftp.com Alistair Banks Microsoft Corporation alistair@microsoft.com Rob Barrow JSB Corporation robb@jsb.co.uk Carl Beame Beame & Whiteside beame@mcmaster,ca Dave Beaver Microsoft Corporation dbeaver@microsoft.com Amatzia BenArtzi NetManage, Inc. amatzia@netmanage.com Mark Beyer Ungermann-Bass mbeyer@ub.com Nelson Bolyard Silicon Graphics, Inc. nelson@sgi.com Pat Bonner Hewlett-Packard p_bonner@cnd.hp.com Derek Brown FTP Software db@wco.ftp.com Malcolm Butler ICL mcab@oasis.icl.co.uk Mike Calbaum Frontier Technologies mike@frontiertech.com Isaac Chan Microsoft Corporation isaacc@microsoft.com Khoji Darbani Informix khoji@informix.com Nestor Fesas Hughes LAN Systems nestor@hls.com Karanja Gakio FTP Software karanja@ftp.com Vikas Garg Distinct vikas@distinct.com Gary Gere Gupta ggere@gupta.com Jim Gilroy Microsoft Corporation jamesg@microsoft.com Bill Hayes Hewlett-Packard billh@hpchdpc.cnd.hp.com Paul Hill MIT pbh@athena.mit.edu Tmima Koren NetManage, Inc. tmima@netmanage.com Hoek Law Citicorp law@dcc.tti.com Graeme Le Roux Moresdawn P/L - Kevin Lewis Novell kevinl@novell.com Roger Lin 3Com roger_lin@3mail.3com.com Terry Lister Hewlett-Packard tel@cnd.hp.com Jeng Long Jiang Wollongong long@twg.com Lee Murach Network Research lee@nrc.com Pete Ostenson Microsoft Corporation peteo@microsoft.com David Pool Spry, Inc. dave@spry.com Bob Quinn FTP Software rcq@ftp.com Glenn Reitsma Hughes LAN Systems glennr@hls.com Brad Rice Age rice@age.com Allen Rochkind 3Com - Jonathan Rosen IBM jrosen@vnet.ibm.com Steve Stokes Novell stoke@novell.com Joseph Tsai 3Com joe_tsai@3mail.3com.com James Van Bokkelen FTP Software jbvb@ftp.com Miles Wu Wollongong wu@twg.com Boris Yanovsky NetManage, Inc. boris@netmanage.com
The Windows Sockets Specification is intended to provide a single API to which application developers can program and multiple network software vendors can conform. Furthermore, in the context of a particular version of Microsoft Windows, it defines a binary interface (ABI) such that an application written to the Windows Sockets API can work with a conformant protocol implementation from any network software vendor. This specification thus defines the library calls and associated semantics to which an application developer can program and which a network software vendor can implement.
Network software which conforms to this Windows Sockets specification will be considered "Windows Sockets Compliant". Suppliers of interfaces which are "Windows Sockets Compliant" shall be referred to as "Windows Sockets Suppliers". To be Windows Sockets Compliant, a vendor must implement 100% of this Windows Sockets specification.
Applications which are capable of operating with any "Windows Sockets Compliant" protocol implementation will be considered as having a "Windows Sockets Interface" and will be referred to as "Windows Sockets Applications".
This version of the Windows Sockets specification defines and documents the use of the API in conjunction with the Internet Protocol Suite (IPS, generally referred to as TCP/IP). Specifically, all Windows Sockets implementations support both stream (TCP) and datagram (UDP) sockets.
While the use of this API with alternative protocol stacks is not precluded (and is expected to be the subject of future revisions of the specification), such usage is beyond the scope of this version of the specification.
Portions of the Windows Sockets specification are derived from material which is Copyright (c) 1982-1986 by the Regents of the University of California. All rights are reserved. The Berkeley Software License Agreement specifies the terms and conditions for redistribution.
Windows Sockets makes provisions for multithreaded Windows processes. A process contains one or more threads of execution. In the Windows 3.1 non-multithreaded world, a task corresponds to a process with a single thread. All references to threads in this document refer to actual "threads" in multithreaded Windows environments. In non multithreaded environments (such as Windows 3.0), use of the term thread refers to a Windows process.
The Microsoft Windows extensions included in Windows Sockets are provided to allow application developers to create software which conforms to the Windows programming model. It is expected that this will facilitate the creation of robust and high-performance applications, and will improve the cooperative multitasking of applications within non-preemptive versions of Windows. With the exception of WSAStartup() and WSACleanup() their use is not mandatory.
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 " Windows Sockets Components".
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 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 to indicate the point at which the out-of-band data was sent. An application can use the SIOCATMARK ioctlsocket() command 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_ACCEPTCON BOOL Socket is listen()ing. FALSE unless a listen() has been performedSO_BROADCAST BOOL Socket is configured FALSE
for the transmission of
broadcast messages.
SO_DEBUG BOOL Debugging is enabled. FALSE (i)
SO_DONTLINGER BOOL If true, the SO_LINGER TRUE
option is disabled..
SO_DONTROUTE BOOL Routing is disabled. FALSE (i)
SO_ERROR int Retrieve error status 0
and clear.
SO_KEEPALIVE BOOL Keepalives are being FALSE
sent.
SO_LINGER struct linger Returns the current l_onoff is 0
FAR * linger options.
SO_OOBINLINE BOOL Out-of-band data is FALSE
being received in the
normal data stream.
SO_RCVBUF int Buffer size for Implementation (i)
receives dependant.
SO_REUSEADDR BOOL The address to which FALSE
this socket is bound
can be used by others.
SO_SNDBUF int Buffer size for sends Implementation (i)
dependant.
SO_TYPE int The type of the socket As created
(e.g. SOCK_STREAM). via socket()
TCP_NODELAY BOOL Disables the Nagle Implementation
algorithm for send dependant.
coalescing.
Notes:
(i) An implementation may silently ignore this option on setsockopt() and return a constant value for getsockopt(), or it may accept a value for setsockopt() and return the corresponding value in getsockopt() without using the value in any way.
socket data type and error values
Error codes -- errno, h_errno & WSAGetLastError()
Blocking routines & EINPROGRESS
Maximum number of sockets supported
In UNIX, all handles, including socket handles, are small, non-negative intergers, 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
&& WSAGetLastError() == WSAEWOULDBLOCK)
{...}
close() & closesocket() In Berkeley Sockets, sockets are represented by standard file descriptors, and so the close() function can be used to close sockets as well as regular files. While nothing in the Windows Sockets API prevents an implementation from using regular file handles to identify sockets, nothing requires it either. Socket descriptors are not presumed to correspond to regular file handles, and file operations such as read(), write(), and close() cannot be assumed to work correctly when applied to socket descriptors.. Sockets must be closed by using the closesocket() routine. Using the close() routine to close a socket is incorrect and the effects of doing so are undefined by this specification.
ioctl() & ioctlsocket()
Various C language run-time systems use the ioctl() routine for purposes unrelated to Windows Sockets. For this reason we have defined the routine ioctlsocket() which is used to handle socket functions which in the Berkeley Software Distribution are performed using ioctl() and fcntl().
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(). 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 cancelled. 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.
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 descriptor 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 descriptor.
getsockname() Retrieve the current name for the specified socket
getsockopt() Retrieve options associated with the specified socket descriptor.
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 descriptors.
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 descriptor.
shutdown() Shut down part of a full-duplex connection.
socket() Create an endpoint for communication and return a socket descriptor.
* The routine can block if acting on a blocking socket.
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 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 will call the blocking hook function 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.
gethostbyaddr()* Retrieve the name(s) and address corresponding to a network address.
gethostname() Retrieve the name of the local host.
gethostbyname()* Retrieve the name(s) and address corresponding to a host name.
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.
Asynchronous select() Mechanism
Accessing a Windows Sockets DLL from an Intermediate DLL
Internal Use of Messages by Windows Sockets Implementations
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 asynchronous message based
WSAAsyncGetServByName() implementation of the standard Berkeley
WSAAsyncGetServByPort() 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
WSAAsyncSelect() allows interest to be declared in the following conditions for a particular socket:
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 Error Codes.
There are (at least) two ways to accomplish this. The simplest method is for the intermediate DLL to have calls similiar 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.
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.
In each routine it is indicated that the header file winsock.h must be included. Header Files 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 FAR PASCAL 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 Yes
If SO_LINGER is set (i.e. the l_onoff field of the linger structure is non-zero; see Socket Options, getsockopt() and setsockopt()) 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" close, because the socket is closed immediately, and any unsent data is lost. Any recv() call on the remote side of the circuit can 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 Socket Options, getsockopt() and setsockopt()), 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 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:
On a blocking socket, the return value indicates success or failure of the connection attempt.
#include <winsock.h>
int PASCAL FAR getpeername(SOCKET s, struct sockaddr FAR * name, int FAR * namelen);
#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);
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 );
Values specified using the ``.'' notation take one of the following forms:
When 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);
#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 ( int 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 size of the buffer supplied. If the datagram is larger than the buffer supplied, 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 abortively disconnected, 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:
#include <winsock.h>
int PASCAL FAR recvfrom ( int 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 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 abortively disconnected, a recvfrom() 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: