Winsock Programmer’s FAQ
Articles: BSD Sockets Compatibility
by Warren Young
So you say you’re a long-time Unix hacker who’s new to
Windows programming? And you’ve heard of this great API called
Winsock that’s compatibile with your beloved BSD sockets,
but try as you might, you just can’t find the
call? Well bunky, this is the article for you.
In the beginning, there was chaos in the world of Windows TCP/IP APIs. A program written for, say, FTP Software’s TCP/IP stack wouldn’t run on JSB’s stack.
Then, sometime in 1990, a bunch of people got together and decided to make one nice, big, compatible API called Windows Sockets that would allow a single program to run on any vendor’s stack. They decided to base this API on the popular BSD sockets model of network programming, but for various reasons, there are still many differences between Winsock and BSD sockets. This article points out how Winsock differs from BSD sockets, and how to translate BSD sockets programs to use similar Winsock functionality.
The Winsock API documentation has a section called Porting Socket Applications to Winsock that covers many of the same issues that this article does, and a few others besides.
Under BSD sockets, there are quite a few different header files you need to include, depending on what sockets calls you use. A typical BSD sockets program has a block of #includes near the top like this:
For Winsock, you don’t need any of these. Instead, you just need to include winsock.h. (Or, if you need Winsock 2-specific functionality, winsock2.h.)
WSAGetLastError() is essentially the same thing as
errno global variable. The error constants and
their values are different; there’s a table in the Winsock
spec where it lists all the error constants, one column of which
shows the equivalent BSD error constant for a given Winsock error
constant. Usually the difference is just the addition of "WSA" to the
beginning of the constant name for the Winsock versions. (E.g. WSAEINTR
is the Winsock version of BSD’s EINTR error constant.)
Another thing to keep in mind is that, although the
call exists in most Windows compilers' run-time libraries, it
doesn’t work for Winsock calls. (This is a consequence
of Winsock not returning its error codes in the
variable.) There is a function called
in the basic Winsock examples area of
the FAQ that you can use to build a
It’s in the ws-util.cpp module.
Many Unix programs, especially those with System V roots, check
for the EAGAIN value in the global
errno variable when
a non-blocking call fails. This is the same thing as BSD’s
EWOULDBLOCK and Winsock’s WSAEWOULDBLOCK errors. You’ll
have to check your system’s header files, but all Unixes
I’ve checked on this matter #define EAGAIN and EWOULDBLOCK
to the same value, so you may want to get into the habit of using
EWOULDBLOCK instead of EAGAIN under Unix, to make transitions to and
from Winsock easier.
Under Unix, the I/O system calls work with file descriptors and
socket descriptors equally well. It’s common in BSD sockets
programs to use
read() instead of
recv() to read
data from a socket, for example. Under Windows 3.1 and Windows 95
derivatives, socket descriptors are completely distinct from file
descriptors. Although the run-time library (RTL) supplied with most
Windows compilers includes POSIX emulation functions, these are
designed to work only with files, not sockets.
Windows NT derivatives are more like Unix, in that its native file
I/O functions also work with sockets:
ReadFile() is roughly
equivalent to Winsock’s
recv() function, for example.
The Visual C++ RTL emulates POSIX functions, except that
they’re named with a leading underscore: for example,
_read() instead of
ReadFile() internally, so you’d think it would work
with sockets. The problem is, the first argument is an RTL-specific
handle, not an operating system file handle. If you pass a socket
_write(), the RTL will realize that
it isn’t an RTL handle and the call will fail.
Fortunately, there is a bridge function in Visual C++’s
_open_osfhandle(). (If you’re not using Visual
C++, you’ll have to check its RTL source for a similar
function.) I’ve not tried it, but it appears to take an operating
system file handle (including socket handles) and return a handle you
can use with the POSIX emulation functions in the RTL. I’m told
that this will work with sanely-coded non-Microsoft Winsock stacks,
but since I haven’t tried it, you should if you want to support
these alternate stacks.
_open_osfhandle() workaround only works on
Windows NT derivatives, because the file I/O functions don’t
work with sockets on the Windows 95 derivatives, so fooling the RTL
into accepting one doesn’t help you.
If these limitations are too much for your program, you may want to give one of the Unix emulation systems a try. I’ve personally used Cygwin for this purpose, and it works beautifully. Others include Microsoft’s Services for Unix and AT&T’s UWIN, but I’ve not used either of them.
All that aside, it’s usually much easier to rewrite your
program to use portable functions like
recv() than it is to
arm-twist the Windows port to work with Unix idioms.
Winsock defines a different function for closing sockets because not all versions of Windows have file descriptor and socket descriptor equivalency like Unix. See the discussion in the previous item for more on the file/socket handle mismatch issue.
Unix provides the
ioctl() call to allow you to set and get
various bits of info on a file descriptor, which includes socket
descriptors. Winsock replicates some common Unix ioctls in the
ioctlsocket() call, but much is missing.
If you use the
SIOCGIFCONF ioctl on Unix to
get information about the system’s network interfaces,
Winsock 2 provides very similar functionality with its
SIO_GET_INTERFACE_LIST option for
fcntl() call has no direct equivalent
under Winsock. Where necessary, similar functionality exists
ioctlsocket() call. For example, the
equivalent of using Unix’s
fcntl() to set a socket’s
O_NONBLOCK flag is setting the FIONBIO flag with
There are several wrappers for
select() out there. Here’s
one. It doesn’t attempt to implement any of the special
poll() features found in a true System V system, such as
STREAMS support. Also, the code is rather old, written in a K&R
C style that some newer compilers might reject. Finally, since
it is built directly on top of
select(), it has the same
Another option is to dig the implementation
poll() out of Jarle Aasa’s Win32 port of the adns
library. This implementation has three limitations: 1) It’s GPL’d, which
means you can’t use the code in your program unless your program
is also licensed under the GPL; 2) it’s built on the Win32 event
object mechanism, which has a hard
64-object limitation; and 3) it is reportedly not written in a
way that is easy for third-party programmers to extract and use.
Winsock 2’s overlapped I/O mechanism includes scatter/gather
functionality similar to that provided by
dup() function duplicates a file handle, and
of course also works for sockets. Under Winsock 2, you can do the
same thing with
WSADuplicateSocket(). It’s a bit more
involved, but the
WSADuplicateSocket() documentation in MSDN has a good step-by-step
example showing how to use this mechansim.
There is partial support for this feature under Winsock, though
the mechanism is dissimilar to the
dup2() feature. Under Unix,
dup2() takes a handle and duplicates it like
but with a twist: it assigns the new filehandle a value that you
specify. This is usually used to map a socket to the C language’s
stdin or stdout file descriptors so that you can use standard I/O
fgets() with the socket.
Item KB190351 in the Microsoft Knowledge Base documents a method by which you can redirect a child process’s standard descriptors to a socket. The limitations are that you cannot do this to your own process’s descriptors, you cannot redirect arbitrary descriptors to a socket (i.e. you can only do it with stdin, stdout and stderr), and not all processes are fully compatible with this API feature. Still, it at least makes an inetd-like program possible under Win32.
Under BSD Unixes, if the remote peer closes its connection
and your program is blocking on
recv(), you will get
a 0 back from
recv(). Winsock behaves the same way,
except that it can also return -1, with
WSAESHUTDOWN, to signal the detectable flavors of
Under Unix, if you’re blocking on
send() and your
program is ignoring the
SIGPIPE signal, it will return
with a -1 when the remote peer disconnects, and
EPIPE. Otherwise, your program will be sent the SIGPIPE
signal, which will terminate your program if you don’t handle
it. Under Winsock, the SIGPIPE/EPIPE functionality does not exist at
send() will either return 0 for a normal disconnect or -1
for an abnormal disconnect, with
the same errors as in the
recv() discussion above.
According to Ilpo Ruotsalainen, "...most BSD socket implementations
do not pass delayed UDP errors (ICMP port unreachable at least, maybe
others too) to
recvfrom() while Winsock 2 [under Windows 2000
but not Windows 98] does. Linux [behaves like Windows 2000] too,
but provives SO_BSDCOMPAT
setsockopt() for being compatible
with the BSD style."
In other words, a portable program has to be prepared for
the possibility of error codes for non-immediate problems from
recvfrom(), but it can’t depend on receiving them.
This article can always use more work. If you can help me out,
please drop me a line! In particular,
I’ll bet that there are several other BSD-only
options that we can duplicate in other ways with Win32 facilities.
Copyright © 1998-2005 by Warren Young. All rights reserved.
<< The Straight Dope on Packet Sniffers
||WsControl() Revealed >>|
|Updated Sun Feb 28 2010 07:48 MST||Go to my home page|