views:

300

answers:

5

I'm currently in the middle of a project involving sockets, and I just use Linux's sys/socket.h file. Cue the port to Microsoft, and realizing that Winsock is different. I guess I have two questions.

First, what're the main differences between the two implementations? Is there an easy way to "translate" them? A link to a guide would be greatly appreciated, because you guys can probably get me better quality links than Google.

Second, why did Microsoft do this? What was their motivation? Why didn't they just keep the same implementation as everyone else?

+8  A: 

Forgive me if I've missed the point, but are you looking at WSARecv and family, and thinking that the whole sockets API on Windows is different from the Berkeley Sockets API?

The Berkeley API does exist on Windows (see recv and family) and is largely compatible with any other Berkeley Sockets implementation.

See the MSDN article "Porting Socket Applications to Winsock" for information about porting sockets code to Windows.

RichieHindle
Oh no, I didn't think that the whole API was different. Otherwise, how would Windows computers communicate with *nix computers? But I was just wondering why the syntax was different.
Andrew Szeto
@Andrew: "wondering why the syntax was different": my point is that the syntax *isn't* different - the same Berkeley Sockets API that you're using on Linux is also available on Windows. Or are we talking at cross purposes? Do you have an example of how the syntax differs?
RichieHindle
A: 

Try using ACE - it is a great cross platform communications library.

Tim
A: 

Milen said it in a comment, but the Apache Portable Runtime library covers many of the portability issues for networked application.

Novelocrat
A: 

Quoting Wikipedia, saving you the effort for googling:

Windows Sockets is based on BSD sockets, but provides additional functionality to allow the API to comply with the standard Windows programming model. The Windows Sockets API covered almost all the features of the BSD sockets API, but there were some unavoidable obstacles which mostly arose out of fundamental differences between Windows and Unix (though to be fair Windows Sockets differed less from BSD sockets than the latter did from STREAMS). All function calls in the API begin with the moniker WSA, e.g. WSAGetHostByName() for making a hostname lookup. Windows Sockets expanded on BSD Sockets functionality, by offering "non-blocking" or asynchronous Sockets (accessed by adding WSAAsync before the desired function; e.g., WSAAsyncGetHostByName())

However it was a design goal of Windows Sockets that it should be relatively easy for developers to port socket-based applications from Unix to Windows. It was not considered sufficient to create an API which was only useful for newly-written Windows programs. For this reason, Windows Sockets included a number of elements which were designed to facilitate porting. For example, Unix applications were able to use the same errno variable to record both networking errors and errors detected within standard C library functions. Since this was not possible in Windows, Windows Sockets introduced a dedicated function, WSAGetLastError(), to retrieve error information. Such mechanisms were helpful, but application porting remained extremely complex. Many "traditional" TCP/IP applications had been implemented by using system features specific to Unix, such as pseudo terminals and the fork system call, and reproducing such functionality in Windows was problematic. Within a relatively short time, porting gave way to the development of dedicated Windows applications.

ssg
When using material from Wikipedia, please provide a link to the page it comes from (permanent link to the specific revision).
Rob
"All function calls in the API begin with the moniker WSA" - this again implies that Windows forces you to use `WSARecv()` instead of `recv()`, which is not true - `recv()` is alive and well on Windows.
RichieHindle
@Rob, why is that? One reason I can think of is, users may want to ensure the authenticity of my quote, which is meaningless when you think of other web sites which we can quote, and can change easily afterwards. Why is it specifically necessary for Wikipedia?Besides, my quote doesn't have any claim for being truthful. How can it be necessary to link to the specific revision for a quote while I could copy-paste the same paragraphs without specifying that I was quoting Wikipedia? Would that make the statements more authentic?I'm trying to understand why I should bother.
ssg
@Richie, rest of the text explains that. "For this reason, Windows Sockets included a number of elements which were designed to facilitate porting. For example, Unix applications were able to use the same errno variable to record both networking errors and errors detected within standard C library functions."
ssg
+6  A: 

The Winsock Programmer's FAQ has a section on this, BSD Sockets Compatibility. (Disclosure: I'm the FAQ's maintainer.)

I didn't really cover the whys and wherefores in that article, so:

  • winsock.h vs sys/socket.h, arpa/inet.h, netinet/in.h, etc.: This I actually find an improvement. It's all one tight set of functionality, so why not have all the definitions for it in a single header?

  • close() vs. closesocket(): Back in the Windows 3 days when Winsock was invented, Windows C++ compilers all had some kind of POSIX API wrapper to provide some basic level of portability, including close(). These just called down into the compiler's stdio implementation, since DOS and Win16 didn't have a unified I/O mechanism like Unices do. You can't just call close() on a descriptor in Win16 and have it work independent of whether it's a file, socket, pipe, whatever. Win32 existed at the same time as Winsock was being invented as part of NT 3.5, and it fixes this, but making Winsock available only on NT derivatives would have made MS irrelevant on the Internet until Windows XP. MS can be slow to the game, but not that slow. Bottom line, anything in BSD sockets that uses POSIX mechanisms that conflicted with existing APIs provided by the C++ compilers that targeted it just couldn't be in Winsock. They had to give the same functionality a new name.

  • WSA*(): This is just added functionality, providing functionality that BSD sockets doesn't. A lot of it is really nice, and it'd be nice to see similar mechanisms across all Unices, but that's not going to happen any time soon. There are competing mechanisms, like aio*(), but that isn't available across all Unices, much less portable to Windows. You can just ignore it and stick to the base sockets APIs, though this isn't always the best choice when porting to Windows.

  • errno vs. WSAGetLastError(): errno is part of Standard C, but the error values are up to the C implementation. Keep in mind that Winsock in the beginning was not a Microsoft-specific thing. DOS and Windows didn't start off having standard network APIs. This was provided by third parties, who all got together and invented Winsock, with Microsoft involved. The initial Winsock stacks were all third-party. They couldn't write the spec to be overwriting the C RTL's errno value, for several reasons. These error values belonged to the vendor-provided winsock.dll, a whole different world from the C RTL.

  • WSAStartup(), WSACleanup(): Again this is due to the fact that winsock.dll was initially a third-party provided thing, which interfaced with some underlying network stack that isn't part of the OS. Also, there's the Win16 aspect of things: Win16 couldn't see that a program just died and clean up its allocated resources automatically. You had to explicitly release everything before the program exited, or they'd be leaked.

  • Lack of readv(), etc.: This didn't make sense in the third-party/Win16 world where Winsock was born.

Warren Young