Differences Between Windows and Unix Non-Blocking Sockets

Posted 15 Jun 2003 at 23:37 UTC by itamar Share This

While working on Twisted's networking, I discovered a series of differences between socket APIs on Windows and Unix/Linux. This article is intended to document them for the benefit of those who are developing their own networking code.

While working on Twisted's networking, I discovered a series of differences between socket APIs on Windows and Unix/Linux. This article is intended to document them for the benefit of those who are developing their own networking code.

The permanent home of this article will be on my homepage, where I will add anything new I discover or I receive from other people. Please add comments to the article if you know of any other differences.

Some caveats:

  • This document only discusses non-blocking sockets.
  • I am not an expert on either Unix or Windows or networking. On the other hand Twisted has an extensive set of tests and runs numerous real programs on both platforms.
  • These results were based on Python's behavior, as is my terminology. Since Python wraps the C APIs in a very light weight way, and I haven't found major contradictions between its behavior and MSDN and Unix documentation, this information is probably valid for C networking as well.

My main sources of information were the relevant MSDN pages, Volume 1 of Unix Network Programming (2nd Edition), and experimentation and results from running systems. I recommend all three for verifying this information.

Without further ado, here are the differences (I may have forgotten some):

WSA errnos
Socket APIs will return WSA errnos, rather than the standard ones (e.g. WSAEWOULDBLOCK, although Windows also has EWOULDBLOCK). Except when they don't. Refer to MSDN.

select(2) doesn't block on empty lists of fds
If you don't pass any socket fds to select(2) on Unix, it will block for the specified timeout. On Windows, it will return immediately with an error. This may be a Python oddity.

Peculiar errnos from select(2)
I've seen errnos 0 and 2 returned on Win32 for no reason I understood, apparently when passing empty read or write list.

Detecting failed connects is done using exception list of select(2)
On Unix, a failed connect will return an error upon reading or writing from the socket, and select() will mark the socket as notified. The exception list in select(2) is used for detecting OOB data. On Windows, not the read or write lists but rather the exception list is used for detecting failed connects.

Failed connects, reads and writes still return WSAEWOULDBLOCK
Reads or writes to the socket will return a WSAEWOULDBLOCK even if connection failed. The errno is available via getsockopt with SO_ERROR.

WSAEINVAL is equivalent to WSAEWOULDBLOCK for connect(2)
You need to treat both as equivalent on Windows.

On Windows it lets you bind to the same TCP port multiple times without errors.

UDP blocking on recvfrom returns WSAECONNRESET for connection refused
On Unix you get ECONNREFUSED.

what about IO completion, posted 16 Jun 2003 at 01:04 UTC by eckes » (Master)

I think to utilize the full power of Win32 networking, one would use the WSA Event methods and work with the normal event functions, and not use the berkley wrappers.

This will also support threaded parallel usage of Overlapped IO completion. How about using them in the Framework?

Indeed, posted 16 Jun 2003 at 01:26 UTC by itamar » (Master)

I wrote code for this a while back, but never finished it for lack of interest, time and a real Windows machine. Plus we had a lot less tests at the time, and non-finalized APIs, so finding where the bugs were was hard. It was basically working though.

At some point we will have this (faster if someone pays me, donates a MSDN subscription or writes it themselves ;). But until we do, working code is better than no code.

For many people, porting their BSD socket code will be much easier than rewriting, and thus this article.

Unspoken Purpose, posted 16 Jun 2003 at 01:43 UTC by glyph » (Master)

The real point of this article, of course, is:

Do Not Write Your Own Portable Networking Layer.

It is fairly difficult and subtle to get networking code to work even with the BSD wrappers on Windows. A network layer, even one that is only portable between different UNIXes, requires considerably more effort than reading a few pages of UNP and the man page for socket(2).

Twisted, hopefully, will have support for the more advanced IO completion facilities on Win32 (and, for that matter, the aio facilities on linux), but in the meanwhile, if you are trying to write a portable network application, consider donating some porting effort to an existing framework rather than writing one from the ground up.

If Python isn't to your taste, I've heard a few good things about gnet. Of course, I have a bias, but I think you should use Twisted.

If I remember correctly..., posted 16 Jun 2003 at 02:55 UTC by tk » (Observer)

...the Cygwin people have also tackled such problems before.

I found something that dose this...., posted 16 Jun 2003 at 13:16 UTC by SyOpReigm » (Journeyer)

Link: http://cs.ecs.baylor.edu/~donahoo/practical/CSockets/practical/

Warning: Whle this is very easy to use, readability is chosen over speed, and it as yet hasn't been tested for security.

For low-level wrapping of socket APIs, posted 16 Jun 2003 at 14:11 UTC by itamar » (Master)

The Python socket module source code is probably an excellent guide.

One of the better books on the subject, posted 17 Jun 2003 at 21:00 UTC by robocoder » (Journeyer)

Quinn, Bob, and Dave Shute. Windows Sockets Network Programming. Addison-Wesley, 1996. ISBN: 0-201-63372-8

It covers Winsock 1.1 and 2.0, differences (and porting from) BSD sockets, etc.

New Advogato Features

New HTML Parser: The long-awaited libxml2 based HTML parser code is live. It needs further work but already handles most markup better than the original parser.

Keep up with the latest Advogato features by reading the Advogato status blog.

If you're a C programmer with some spare time, take a look at the mod_virgule project page and help us with one of the tasks on the ToDo list!

Share this page