📄 advanced.html
字号:
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0//EN"><html lang="en"><head><title>Winsock Programmer's FAQ: Advanced Winsock Issues</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="intermediate.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 4: Advanced Winsock Issues<br> </b></p> </font> </td> <td align="right" bgcolor="#e0e0c0"> <font size="2" face=Verdana,Arial,Helvetica> <b><a href="resources/index.html">>></a></b> </font> </td> </tr></table><!-- ---- Body Table ---- --><table width="95%" border="0" cellpadding="10"> <tr valign="top"> <td><a name="rawsocket"></a><h5>4.1 - How can I open a raw data socket?</h5><p>Under Winsock 1.1, the SOCK_RAW socket type is optional. Some ofthe non-Microsoft stacks implemented it, but these implementations areincreasingly hard to find. SOCK_RAW in Winsock 1.1 is also problematicbecause the Winsock spec's writers did not try to rigorously definewhat we should expect from a SOCK_RAW implementation.</p><p>The Winsock 2 spec gives more details about raw sockets,and Microsoft's Winsock 2 stacks do implement some types of rawsockets. Windows 2000 has by far the best implementation of rawsockets; details below.</p><p>On all other platforms, raw socket support is fairly sparse:Microsoft only supports raw IGMP and ICMP sockets on these platforms.The latter allows you to <a href="examples/rawping.html">send "ping"packets</a> in a standard way. These stacks <i>do not</i> supportraw IP or "packet capturing" from the Winsock layer. (See the next twoquestions for information on <a href="#pktcapture">capturing packets</a>and <a href="#pktheader">changing packet headers</a>.)</p><p>If you really must have complete raw sockets support and can't useWindows 2000, you might think about a platform change. Most flavors ofUnix (including the free BSD flavors and Linux) have good raw socketsupport.</p><p>Available raw sockets support in Microsoft stacks:</p><table align=center border=0 cellspacing=0 cellpadding=5> <tr align=center bgcolor="#FBFDB0"> <td> </td> <td><b>Winsock 1.1<br>(all platforms)</b></td> <td><b>Win9x with<br>Winsock 2</b></td> <td><b>WinNT 4.0</b></td> <td><b>Windows 2000</b></td> </tr> <tr align=center> <td bgcolor="#FBFDB0"><b>Raw I[CG]MP</b></td> <td bgcolor="#F4D7AA">No</td> <td bgcolor="#F4D7AA">Yes</td> <td bgcolor="#F4D7AA">Yes</td> <td bgcolor="#F4D7AA">Yes</td> </tr> <tr align=center> <td bgcolor="#FBFDB0"><b>IP_HDRINCL</b></td> <td bgcolor="#F4D7AA">No</td> <td bgcolor="#F4D7AA">No</td> <td bgcolor="#F4D7AA">No</td> <td bgcolor="#F4D7AA">Yes</td> </tr> <tr align=center> <td bgcolor="#FBFDB0"><b>Raw TCP/UDP</b></td> <td bgcolor="#F4D7AA">No</td> <td bgcolor="#F4D7AA">No</td> <td bgcolor="#F4D7AA">No</td> <td bgcolor="#F4D7AA">No</td> </tr> <tr align=center> <td><img src="./bitmaps/dot-clear.gif" alt="" width=100 height=1></td> <td><img src="./bitmaps/dot-clear.gif" alt="" width=100 height=1></td> <td><img src="./bitmaps/dot-clear.gif" alt="" width=100 height=1></td> <td><img src="./bitmaps/dot-clear.gif" alt="" width=100 height=1></td> <td><img src="./bitmaps/dot-clear.gif" alt="" width=100 height=1></td> </tr></table><p>Notice that raw TCP and UDP aren't possible directly under Winsock 2.Instead, you must use IP_HDRINCL (a.k.a. raw IP) and build your own IP<i>and</i> TCP or UDP headers.</p><a name="pktcapture"></a><h5>4.2 - How can I capture packets on a LAN with Winsock?</h5><p>You cannot. Winsock (at least as implemented by Microsoft) does notallow promiscuous IP packet captures.</p><p>So how do Ethernet analyzers work, you ask? They talk straight to theTransport Data Interface (TDI) or Network Device Interface Specification(NDIS) layer. The TDI layer is just above the system's NDIS (networkdriver) layer. Some of the Windows packet sniffers in the FAQ's <ahref="resources/debugging.html">debugging resources section</a> includesource, which you could pick apart to figure out how this works.</p><p><a href="http://www.pcausa.com/">PCAUSA</a> sells a packagethat is supposed to make writing to the TDI and NDIS layerseasier. I have, however, not tried this product. They also have <ahref="http://www.pcausa.com/resources/">several FAQs</a> that talkabout various low-level network stack access methods. These FAQs alsopoint you to various bits of sample code, most of it from Microsoft'svarious DDKs.</p><p>If all you want is a way to help you debug your Winsock program byshowing you what is happening on the network, the Resources sectionmentioned above has links to many capable network sniffers and otherdebugging tools.</p><a name="pktheader"></a><h5>4.3 - How can I change the IP or TCP header of a packet?</h5><p>That's only possible under Windows 2000 with Winsock, at this time.A few IP header fields can be set with <code>setsockopt()</code> and/or<code>ioctlsocket()</code>. One such field is TTL.</p><p>If that is not enough control for your application, you will have toresort to lower-level techniques. One of these is to add a layer to thenetwork stack with Winsock 2's Layered Service Provider mechanism. Thatmechanism is not covered in this FAQ, but there is some useful codeand documentation on the <a href="http://msdn.microsoft.com/">MSDN</a>site and disks.</p><p>Another option is to do raw data I/O using the TransportData Interface (TDI) or the Network Driver InterfaceSpecification (NDIS). Further information is available in <ahref="http://www.pcausa.com/resources/">PCAUSA's FAQs</a>.</p><p>Also, don't rule out the option of building your application on aplatform that <i>does</i> have easy access to the packet headers. MostUnix flavors (including Linux) offer copious tools for low-level networkI/O. For information on raw network programming on Unixlike platforms,see Thamer Al-Herbish's <a href=" http://www.whitefang.com/rin/">Raw IPNetworking FAQ</a>.</p><a name="ping"></a><h5>4.4 - How can I "ping" another machine with Winsock?</h5><p>The "official" method uses the IPPROTO_ICMP raw socket type definedby Winsock 2. All of Microsoft's Winsock 2 stacks support this. I suspectthat this also works on some non-Microsoft Winsock 1.1 stacks, but I don'tpersonally know of any such success. <a href="examples/rawping.html">[C++example]</a></p><p>The other method uses ICMP.DLL, which is an extension specific toMicrosoft stacks. Though it works on all Windows systems as of thiswriting, Microsoft discourages its use in the strongest terms possible,claiming that the API will disappear as soon as a better methodexists. (It hasn't actually happened yet, despite several years ofthreats. :) ) ICMP.DLL's main advantage is that it works under Winsock1.1. It is, however, less flexible than the raw sockets method. <ahref="examples/dllping.html">[C++ example]</a></p><p>I want to point out that many programs misuse ping. Naturally it hasgood uses, but it's a sign of a broken program or protocol if you findyourself resorting to regular use of ping packets. For example, I'malways seeing people ask about pinging when what they really want is to<a href="newbie.html#abnormalclose">detect dropped connections</a>.</p><a name="fdpass"></a><h5>4.5 - How do I pass a socket from one process to another?</h5><p>This is not possible under Winsock 1.1, because it wasn't consideredsufficiently important at the time the spec was created.</p><p>Winsock 2 provides support for this through the<code>WSADuplicateSocket()</code> facility. The spec describes thismethod in detail, including some example code. Another interestingsource of information about this is Microsoft Knowledge Base article<a href="http://support.microsoft.com/support/kb/articles/q150/5/23.asp">Q150523</a>, which describes how socket inheritance differsbetween the various flavors of Windows.</p><p>Another fun feature of the Win32 API is that it allows you to give anew process different "standard handles" (stdin, stdout and stderr) whenyou create it. Article <a href="http://support.microsoft.com/support/kb/articles/q190/3/51.asp">Q190351</a> in the Microsoft KnowledgeBase addresses this. Note that this feature only allows you to do thiswith a child process; you can't redirect your own standard I/O handlesto a socket. Also, the item notes that some processes may behave stangelywhen you do this to them. Clearly, this functionality is not as powerfulas the Unix world's <code>dup2()</code> system call.</p><a name="dllsockets"></a><h5>4.6 - Is it possible to create sockets that map to a DLL rather than an application?</h5><p>Under Windows, a DLL's data is actually owned by the applicationthat loads the DLL. If you need the DLL to own a single socket no matterhow many processes load the DLL, you need to create a "helper process"which will perform all Winsock operations on behalf of the DLL. Naturallyyou'll need some kind of interprocess communication channel between theDLL and the helper process.</p><p>Note that this issue only matters if you're using a DLL to let multipleprocesses share a socket. If you only have one process using the DLL,or if it's okay for each process to remain ignorant of the other processesusing the DLL, this issue won't matter to you.</p><a name="snmp"></a><h5>4.7 - How can I get access to the {route, ARP, interface, etc.} table?</h5><p>Stas Khirman and Raz Galili have written a <ahref="http://www.caip.rutgers.edu/~arni/ws2/stas.htm">great tutorial</a>on the art of using the poorly-documented SNMP API. This API allowsyou to access many "hidden" parts of the Windows networking subsystem,including the network interface list, the route and ARP tables, the listof connected network sockets, your Ethernet cards' hardware addresses,etc.</p><a name="macaddr"></a><h5>4.8 - How do I get the MAC (a.k.a. hardware) address of the local Ethernet adapter?</h5><p>This FAQ has example code for two methods, both of which are somewhatkludgey. The <a href="examples/getmac-netbios.html">first method</a>involves asking the NetBIOS API for the adapter addresses. The primaryproblem with this method is that it sometimes fails, depending on
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -