📄 bsd-compatibility.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"><html lang="en"><head><title>Winsock Programmer's FAQ: Articles</title><link rel="Stylesheet" type="text/css" href="../faq.css"></head><body bgcolor="#ffffee" text="#000000" link="#491e00" vlink="#7d2e01" alink="#da7417"><!-- ---- Header Bar ---- --><table border="0" width="95%" bgcolor="#006000" cellpadding="5" cellspacing="3" align="center"> <tr> <td align="left" bgcolor="#e0e0c0"> <font size="2" face=Verdana,Arial,Helvetica> <b><a href="../articles/debugging-tcp.html"><<</a></b> </font> </td> <td align="center"> <font face=Verdana,Arial,Helvetica color="#ffffee"> <p align=center class=bigger3><b> Winsock Programmer's FAQ<br> Section 7: Articles<br> </b></p> </font> </td> <td align="right" bgcolor="#e0e0c0"> <font size="2" face=Verdana,Arial,Helvetica> <b><a href="../articles/wscontrol.html">>></a></b> </font> </td> </tr></table><!-- ---- Body Table ---- --><table width="95%" border="0" cellpadding="10"> <tr valign="top"> <td><H3>Winsock's Compatibility With BSD Sockets</H3><p><I>by Warren Young</I></p><p>So you say you're a long-time Unix hacker who's new to Windowsprogramming? And you've heard of this great API called Winsock that'scompatibile with your beloved BSD sockets, but try as you might, youjust can't find the <code>readv()</code> call? Well pardner, this isthe article for you.</p><h4>Introduction</h4><p>In the beginning, there was chaos. This chaos was in the form ofincompatible Windows TCP/IP APIs: a program written for, say, FTPSoftware's TCP/IP stack wouldn't run on JSB's stack.</p><p>Then, sometime in 1990, a bunch of people got together and decidedto make one nice, big, compatible API called Windows Sockets that wouldallow a single program to run on any vendor's stack. They decided to basethis API on the popular BSD sockets model of network programming, butfor various reasons, they didn't include every BSD sockets feature. Thisarticle will tell you how to get similar behavior to several BSD featuresusing other Winsock or Win32 facilities.</p><p>This article is still evolving. Each entry below has two dates afterit: an "added" and an optional "modified" date. So, you can periodicallycome back to this document to see if any new BSD-like behaviors have beenuncovered in the Winsock API. Changes to this document will be announcedon the main Winsock Programmer's FAQ page, in the What's New section.</p><p><b><font size=+1><code>dup()</code></code></b></font> <fontsize=-1>(Added 1998.12.24)</font></p><p>The Unix <code>dup()</code> function duplicates a file handle, and ofcourse also works for sockets. Under Winsock 2, you can do the same thingwith <code>WSADuplicateSocket()</code>. It's a bit more involved, but theWinsock spec gives you a canned function call sequence you can use.</p><p>Incidentally, the Winsock method is somewhat more powerful than theUnix version, because you can pass the duplicated socket to an unrelatedprocess without any extra steps, whereas a simple <code>dup()</code>'edsocket under Unix can only be accessed by the process's children.</p><p><b><font size=+1><code>dup2()</code></code></b></font> <fontsize=-1>(Added 1998.12.24, modified 1999.06.27)</font></p><p>There is partial support for this feature under Winsock, thoughthe mechanism is dissimilar to the <code>dup2()</code> feature. UnderUnix, <code>dup2()</code> takes a handle and duplicates it like<code>dup()</code> does, but with a twist: it assigns the new filehandlea value that you specify. This is usually used to map a socket to theC language's stdin or stdout file handles so that you can use standardI/O functions like <code>printf()</code> and <code>fgets()</code> withthe socket.</p><p>Item <a href="http://support.microsoft.com/support/kb/articles/q190/3/51.asp">Q190351</a> in the Microsoft Knowledge Base documentsa method by which you can redirect a child process's standard handlesto a socket. The limitations are that you cannot do this to your ownprocess's handles, you cannot redirect <i>arbitrary</i> handles to asocket (i.e. you can only do it with stdin, stdout and stderr), andnot all processes are fully compatible with this API feature. Still,it at least makes an inetd-like program possible under Win32.</p><p><b><font size=+1><code>errno</code>vs. <code>WSAGetLastError()</code></b></font> <font size=-1>(Added1998.12.24)</font></p><p><code>WSAGetLastError()</code> is essentially the same thing as Unix's<code>errno</code> global variable. There is one small difference,however: <code>WSAGetLastError()</code> is a function call because itworks on a per-thread basis, whereas <code>errno</code> is global to theentire program. This implies that sockets can be used safely by multiplethreads under Winsock, but not necessarily so under Unix. (See themain FAQ for more on <a href="../intermediate.html#threadsafety">threadsafety</a> under Winsock.)</p><p><b><font size=+1>Symbolic Error Values</b></font> <font size=-1>(Added1999.09.25)</font></p><p>Most of the error values that <code>WSAGetLastError()</code> can returncome from BSD, except that Winsock's versions begin with "WSA". Forexample, where a BSD system might use ECONNRESET, Winsock would useWSAECONNRESET. (Insert "gratuitous incompatibility" rant here.)</p><p><b><font size=+1>EAGAIN</b></font> <font size=-1>(Added1998.12.24)</font></p><p>Many Unix programs, especially those with System V roots, checkfor the EAGAIN value in the global <code>errno</code> variable when anon-blocking call fails. This is the same thing as BSD's EWOULDBLOCKand Winsock's WSAEWOULDBLOCK errors. You'll have to check your system'sheader files, but all Unixes I've checked on this matter #define EAGAINand EWOULDBLOCK to the same value, so you may want to get into the habitof using EWOULDBLOCK instead of EAGAIN under Unix, to make transitionsto and from Winsock easier.</p><p><b><font size=+1>readv() and writev()</b></font> <font size=-1>(Added1998.08.01)</font></p><p>BSD sockets' scatter/gather mechanism is very similar to parts ofWinsock 2's overlapped I/O mechanism. Overlapped I/O allows you to passseveral buffers to <code>WSASend()</code> for "gathering" before sendingon the network, and allow incoming data to be "scattered" into severalinput buffers by <code>WSARecv()</code>.</p><p><b><font size=+1>Equivalence of File and Socket Handles</b></font><font size=-1>(Added 1998.08.01)</font></p><p>Under Winsock 1.1, socket handles are completely distinct from the filehandles issued by Win16 and Win32's native I/O facilities. For example,under BSD Unix, you can pass a socket handle to a function that willread from a file. This won't work under Winsock 1.1.</p><p>Winsock 2, with its close ties to Win32, changes this. Under Winsock2, a socket handle is now equivalent to a Win32 file handle. So, theWin32 <code>ReadFile()</code> API is roughly equivalent to good oldWinsock's <code>recv()</code> function. The equivalence is not exact, andcompiler-provided APIs that emulate POSIX APIs like <code>open()</code>,<code>write()</code> and <code>read()</code> may not work with sockethandles, which can make porting some BSD code more difficult that youmight think necessary. Still, it's not as bad as it once was.</p><p><b><font size=+1>Winsock's <code>ioctlsocket()</code>vs. BSD's <code>ioctl()</code></b></font> <font size=-1>(Added1998.08.01)</font></p><p>BSD Unix (and other flavors of Unix) provides the <code>ioctl()</code>call to allow you to set and get various options and behaviorson a socket or file handle. Winsock replicates much of this in its<code>ioctlsocket()</code> call, but not everything is present. However,many of the popular <code>ioctl()</code> options under BSD are avaiablein different forms under Win32 or Winsock.</p><ul> <li><code>SIOCGIFCONF</code> <img src="../bitmaps/waist-dot.gif"alt="--" width=14 height=6 hspace=2> This <code>ioctl()</code>option allows you to get information about the network interfacesavailable. Winsock 2 provides very similar functionality with its<code>SIO_GET_INTERFACE_LIST</code> option for <code>ioctlsocket()</code>.</ul><p><b><font size=+1>Detecting a Dropped Connection</b></font> <fontsize=-1>(Added 1999.09.25)</font></p><p>Under BSD Unixes, if the remote peer closes its connection and yourprogram is blocking on <code>recv()</code>, you will get a 0 back from<code>recv()</code>. If you're blocking on <code>send()</code> and you'veblocked the <code>SIGPIPE</code> signal, it will return with a -1, and<code>errno</code> will be <code>EPIPE</code>; otherwise your programwill be terminated.</p><p>Things are different under Winsock. <code>recv()</code>behaves roughly the same, except that it can also return -1, with<code>WSAGetLastError()</code> returning <code>WSAECONNRESET</code>,<code>WSAECONNABORTED</code> or <code>WSAESHUTDOWN</code>, to signalthe detectable flavors of abnormal disconnections. <code>send()</code>can return with these codes as well; unlike BSD, however, a brokenconnection <i>never</i> kills the process under Winsock, nor does itsend your program a <code>SIGPIPE</code> signal.</p><h4>A Cry For Updates</h4><p>This article can always use more work. As it is, it gives a few goodbits of info about BSD-like behavior under Winsock, but there are stillmany, many holes left to fill. If you can help me out, please drop me aline! In particular, the <code>fcntl()</code> call is not covered at all,and I'll bet that there are several other BSD-only <code>ioctl()</code>options that we can duplicate in other ways with Win32 facilities.</p><p><font size=-1>Copyright © 1998-1999 by Warren Young. All rightsreserved.</font></p> </td> </tr></table><!-- ---- Document Footer ---- --><hr noshade size=1 color=#404040><table cellpadding=5 cellspacing=0 border=0 width=95% align=center> <tr> <td align=left> <a href="../articles/debugging-tcp.html"><< Debugging TCP</a> </td> <td align=right> <a href="../articles/wscontrol.html">WsControl() Revealed >></a> </td> </tr> <tr> <td align=left> <i>Last modified on 29 April 2000 at 15:52 UTC-7</i> </td> <td align=right> <font size=-1>Please send corrections to <a href="mailto:tangent@cyberport.com">tangent@cyberport.com</a>.</font> </td> </tr> </table> <table cellpadding=5 cellspacing=0 border=0 width=95% align=center> <tr> <td align=left width=33%> <font size=-1> <a href="../index.html"><b><</b> Go to the main FAQ page</a> </font> </td> <td width=33%> <font size=-1> <center> <a href="http://www.cyberport.com/~tangent/programming"><b><<</b> Go to my Programming pages</a> </center> </font> </td> <td align=right width=33%> <font size=-1> <a href="http://www.cyberport.com/~tangent/"><b><<<</b> Go to my Home Page</a> </font> </td> </tr> </table> </body></html>
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -