Under Winsock 1.1, the SOCK_RAW socket type is optional. Many major Winsock vendors implement it, but Microsoft's stacks do not.
SOCK_RAW was not mandated in Winsock 1.1 because: 1) not every stack vendor can supply a complete SOCK_RAW interface, and 2) the Winsock spec's writers decided not to mess with the problem of how "raw" a SOCK_RAW connection should be. Since the spec does not enlighten us as to what we should expect from a SOCK_RAW implementation, it is hard to give examples of "proper" use.
The Winsock 2 spec gives more details about raw sockets, and Microsoft's Winsock 2 stacks do implement some types of raw sockets. Unfortunately, this support is fairly sparse. So far as I can tell, Microsoft only supports raw IGMP and ICMP sockets, the latter so that programs can send "ping" packets. (See the raw sockets ping example for an program that uses this functionality.) Microsoft stacks do not support raw IP or "packet capturing" from the Winsock layer, supposedly so people can't write IP spoofing programs and packet sniffers. This is somewhat understandable given that Windows 95 has essentially no security, so you couldn't do things like lock out raw sockets for unprivileged users. (See Questions 3.13 and 3.14 for more information.)
Other Winsocks may provide more raw sockets capabilities, but keep in mind that using this support might tie your program to their particular Winsock implementation.
The "official" method uses the IPPROTO_ICMP raw socket type defined by Winsock 2. I have tested this method under Windows NT 4.0, and it works well. Reports indicate that it works under Windows 95 with the Winsock 2 SDK as well. Note that this code might actually work under some non-Microsoft Winsock 1.1 stacks, but I have heard no such reports. [C++ example]
The other method uses ICMP.DLL, which is an extension specific to Microsoft stacks. While it does currently work, Microsoft discourages its use in the strongest terms possible, claiming that the API will disappear as soon as a better method exists. Nevertheless, Microsoft issued this warning a year or two before Windows 98 came out, and Windows 98 still has a working ICMP.DLL. ICMP.DLL's main advantage is that it works under Winsock 1.1, while the raw sockets method generally does not. [C++ example]
I want to point out that if your program needs to ping another machine, it can simply be the result of a poorly-designed protocol, rather than an actual need. Granted, it can be used to provide more effective feedback in your program, but you shouldn't rely on it for issues like connection checking. For example, I'm always seeing people ask about pinging when what they really want is to use asynchronous sockets, so they can monitor the FD_CLOSE event. (See Tutorial 1 for more ranting about blocking sockets and such.)
This is not possible under Winsock 1.1, because it wasn't considered sufficiently important at the time the spec was created.
Winsock 2, however, does provide support for this through the WSADuplicateSocket() facility. The spec describes this method in more detail. Another interesting source of information about this is Microsoft Knowledge Base article Q150523, which describes the difference between socket inheritance between Windows 95 and Windows NT.
Stas Khirman and Raz Galili have written a great tutorial on the art of using the poorly-documented SNMP API. This API allows you to access many "hidden" parts of the Windows networking subsystem, including the network interface list, the route and ARP tables, the list of connected network sockets, your Ethernet cards' hardware addresses, etc.
There are a few ways. The easiest is to use the Win32 call GetUserName(). [C++ Example].
The other way is shown in the Microsoft Knowledge Base article Q155698 ("How To Look Up Current User Name and Domain Name"). It is much more complex, and it shows two completely different methods, one for Windows 95/Windows 3.1 and one for Windows NT. Unless you need Windows 3.1 support or the LAN Manager domain name (as opposed to the DNS domain name), I suggest you give this article a miss.
Under Windows, a DLL's data is actually owned by the application that loads the DLL. The way to get around this is to have your DLL create a "helper process" which will perform all Winsock operations on behalf of the DLL, because then the helper process owns the sockets.
This issue is covered in detail in Tutorial 3.
The second method depends on a property of the Remote Procedure Call specification that says that the last 6 bytes of a UUID will be derived from the hardware address of the local machine's network adapter. In the case of Ethernet (the common case), this is the MAC address. The major problem with this method is that it will only return one address; if there is more than one Ethernet network adapter in the system, this method won't let you get that second adapter's address.
The descriptions introducing each example go into these issues further.
Yes. However, keep in mind that Winsock is not thread-safe. For example, if one thread is interrupted by the operating system's scheduler while executing a call to recv() and another thread in the same program calls recv() on that same socket before the first thread gets control again, havoc will result. Furthermore, Winsock doesn't even guarantee safety among separate calls, so it may be possible for an application with one thread calling send() and another thread calling recv() to have problems.
If you must let multiple threads access a single socket, you need to carefully serialize the calls that use it. Only testing can show for certain how paranoid you need to be about this. To be perfectly safe, you should completely serialize access to the socket such that only one Winsock call can be made at a time to that socket. Naturally, this defeats the whole purpose of threads, but I have it on good authority that anything less may not be good enough with at least one very common Winsock implementation. The moral of the story may be to limit yourself to one thread per socket.
No. Winsock does not duplicate data among threads. If you protect your program as Question 3.9 recommends, only one thread will receive any given piece of data.
No. If two threads call WSAAsyncSelect() on a single socket, only the thread that made the last call to WSAAsyncSelect() will receive further notification messages. Similarly, if two threads call WSAEventSelect() on a socket, only the event object used in the last call will be signaled when an event occurs on that socket. You also can't call WSAAsyncSelect() on a socket in one thread and WSAEventSelect() on that same socket in another thread, because the calls are mutually exclusive for any single socket. Finally, you cannot reliably call select() on a single socket from two threads and get the same notifications in each, because one thread could clear or cause an event, which would change the events that the other thread sees.
Although this is not a Winsock question per se, it is sometimes useful for a Winsock program to only do its thing if the computer is already connected to the Internet. Before implementing this, however, keep in mind that many computers are not connected to the Internet through a modem. Often, they are connected to a LAN, and that LAN is somehow gatewayed to the Internet. For these situations, the following call will fool your program into believing that the user either has no Internet connection, or that it is never up.
Having said that, the Remote Access Service (RAS) API gives an application access to the dial-up networking subsystem. In particular, the RasEnumConnections() call lets you easily get a list of the connected modems.
You cannot. Winsock (at least as implemented by Microsoft) does not allow promiscuous IP packet captures, unlike, say, most versions of Unix. My personal feeling is that this is probably a good thing because Windows 95 has essentially no security. Since packet capturing is a security hole big enough to drive a DLT tape through (to mix a metaphor), the only solution is to simply not make the feature available.
So how do commercial Ethernet analyzers work, you ask? They talk straight to the NDIS network driver layer. I am told that the Windows NT Device Driver Kit (available with the Professional Level of MSDN) comes with a passable start at an Ethernet analyzer. Also, PCAUSA sells a package that is supposed to make writing to the NDIS layer easier. I have, however, not tried this product.
If all you want is a way to help you debug your Winsock program by showing you what is happening on the network, check out Section 4.5 of the Resources portion of the FAQ.
Sorry, that's not possible, because Microsoft Winsocks do not support either raw IP or TCP sockets, or the IP_HDRINCL option. A few IP header fields can be set, however, with setsockopt() and/or ioctlsocket(). One such field is TTL. I do not know of any vendor that does offer a stack that supports raw IP or TCP sockets.
Generally, almost never.
Inexperienced Winsockers usually try disabling the Nagle algorithm when they are trying to impose some kind of "packet" scheme on a TCP data stream. That is, they want to be able to send, say, two packets, one 40 bytes and the other 60, and have the receiver get a 40-byte packet followed by a separate 60-byte packet. (With the Nagle algorithm enabled, TCP will often coalesce these two packets into a single 100 byte packet.) Unfortunately, this is futile, for the following reasons:
Even if the sender manages to send its packets individually, the receiving TCP/IP stack may still coalesce the received packets into a single packet. This can happen any time the sender can send data faster than the receiver can deal with it.
Turning off the Nagle algorithm in a client program will not affect the way that the server sends packets, and vice versa.
Routers and other intermediaries on the network can fragment packets, and there is no guarantee of "proper" reassembly with stream protocols. Similarly, when sending packets larger than a network medium's MTU, fragmentation will result.
If the network stack runs out of buffers, it may fragment a packet, queuing up as many bytes as it has buffer space for and discarding the rest.
Aside from these problems, disabling the Nagle algorithm almost always causes a program's throughput to degrade. The only time you should disable the algorithm is when some other consideration, such as packet timing, is more important than throughput.
Often, programs that deal with real-time user input will disable the Nagle algorithm to achieve the snappiest possible response, at the expense of network bandwidth. Three examples are Telnet clients, X Windows servers, and multiplayer network games. In all three cases, it is more important that there be as little delay between packets as possible than it is to conserve network bandwidth.
Note that this is a changable issue: back when network bandwidth was truly scarce, Telnet clients usually enabled the Nagle algorithm to save on bandwidth. A contributing factor was that user interfaces in those days tended to be line oriented, whereas modern ones are real-time, with each keystroke potentially changing the entire display. The moral is, consider your application and resources carefully before deciding to disable the Nagle algorithm.
So what, then, is the Right Way to impose a packet scheme on a stream protocol like TCP? The two most common methods are to either use some form of unique delimiter between packets or to use a length prefix. An example of the former is separating packets with, say, a caret (^). An example of the latter is prepending a two-byte integral length value before every packet. I favor the latter, because as soon as you read the length prefix, you know how many more bytes to expect. By contrast, delimiters require that you blindly read until you find the end of the packet.
For more on this topic, see item 19 in The Lame List.
There is no limit set by the Winsock specification, so the only way to tell is to try it on all the Winsock stacks you plan on supporting. [C++ Example]. Keep in mind that whatever value you find for your stack, that this value will change depending on the amount of free system resources. So, you are best off doing this testing on a heavily-loaded machine with the bare minimum hardware configuration that you want to support.
You can, but in practice it may not work. Poorly-written Winsock stacks and Layered Service Providers may limit themselves internally to the default value of FD_SETSIZE, 64. However, you can write a test program to try this on the systems you plan on supporting, to see if they are not limited. Also, you can always send each group of 64 sockets to a different thread, so that several calls to select() can occur simultaneously.
On a machine with multiple network interfaces (a modem for dialup Internet and a LAN card, for example), it can sometimes be useful to force Winsock to use a specific interface. Before I go into how, keep in mind that the routing layer of the stack exists to handle this for you. If your setup isn't working the way you want, maybe you just need to change the routing tables. (This is done with the "route" and "netstat -r" commands on Microsoft stacks.)
There are two common reasons why you might want to force Winsock to use a particular network interface. The first is when you only want your server program to handle incoming connections on a particular interface. For example, if you have an NT machine set up as an Internet gateway, and it also runs a server that you only want internal LAN users to be able to access, you will want to set it to only listen on the LAN interface. The other reason is that you have two or more possible outgoing routes, and you want your client program to connect using a particular one without the routing layer getting in the way.
You can do both of these things with the bind() function. Using one of the "get my IP addresses" examples, you can present your user with a list of possible addresses. Then they can pick the appropriate address to use, which your program will use in the bind() call. Obviously, this is only feasible for programs intended for advanced users.
Incidentally, this is how virtual hosting on the Internet works. A single server is set up with a single network card but several IP addresses. (Most Unixes can do this, as can Windows NT. To set this up, go into the TCP/IP area of the Network control panel, and then click the Advanced button. IIRC, you can enter up to five network addresses per interface.) Then, one web server program is run per interface, with each program only listening to the interface that it has been allocated. When a network connection comes in on one of the virtual interfaces, Winsock routes the connection request to the appropriate web server instance.
Most firewalls support the SOCKS protocol for this purpose, either version 4 or version 5. SOCKS allows a client machine on a protected internal network to ask the firewall to act as a relay between it and an Internet host. SOCKS version 5 adds UDP support, as well as some advanced features like end-to-end encryption and secure logins. It's overkill for most applications, but some servers require that you use a SOCKS5-compatible login to get through.
You can find out more about SOCKS at the NEC SOCKS site (code, a FAQ and SOCKSCap (see below)) and at Stardust's SOCKS Summit 98 site (white paper and other info). You may also want to read the SOCKS5 RFC. Note that a clarified version of this RFC is due out soon; I'll update this Question as soon as I find out about it.
The NEC site has a good and free "SOCKSifier" called SOCKSCap that turns almost any Winsock program into a SOCKS-compliant program, so you may not need to modify your app. (There are other vendors that offer SOCKSifiers, and a few non-Microsoft Winsock stacks are SOCKSified. Check your stack's documentation to see if it supports SOCKS natively.) The SOCKSifier method's downside is that your users must set up SOCKSCap and that they must run your program through the SOCKSifier. Thus, it's more user-friendly to implement the SOCKS protocol directly. There is some BSD sockets client-side SOCKS code at the NEC site that you can easily modify to work with Winsock. This is included as part of the Unix SOCKS server package as a library that the included utility programs (rtelnet, rping, etc.) all link to.
Note that a SOCKSifier is not even an option for some protocols because of the way they operate. Examples of this are RealAudio and almost any "multiuser" protocol, such as multiplayer online games and chat programs. For these programs, you will have to implement the SOCKS protocol directly the NEC code will work for this. Note that some firewalls get around this problem by using knowledge about the protocol to modify its data stream so that you don't have to modify the programs. Unfortunately, modules to do this usually only exist for well-established protocols like RealAudio.
It's occasionally justifiable, but most of the time it's a very bad idea.
I've only heard of two good uses of this feature. The first is when your program needs to bind to a port in a particular range. Some implementations of the Berkeley "r commands" (e.g. rlogin, rsh, rcp, etc.) do this for security purposes. Because only the superuser on a Unix system can bind to a low-numbered port (1-1023), such an r command tries, sequentially, to bind to one of the ports in this range until it succeeds. This allows the remote server to surmise that if the connection is coming from a low-numbered port, the remote user must be a superuser.
The second justifiable example is FTP in its "receive file" mode: it binds to a random port and then tells the file server to "send the file to this port". This is justifiable because it arguably cleans up the protocol, and the FTP client doesn't need to bind to any particular port, it just needs to bind to a port. (Incidentally, it does this by binding to port 0 the stack chooses an available port when you do this.) This is also justifiable because the FTP client is acting as a server in this case, so it makes sense that it has to bind to a port.
By contrast, it is almost always an error to bind to a particular port in a client. (Notice that both of the above examples are flexible about the ports they bind to.) To see why this is bad, consider a web browser. They often create several connections to download a single web page, one each to fetch all of the individual pieces of the page: images, applets, sound clips, etc. If they always bound to a particular local port, they could only have one connection going at a time. Also, you couldn't have a second instance of the web browser downloading another page at the same time.
That's not the biggest problem, though. When you close a TCP connection, it goes into the TIME_WAIT state for a short period (between 30 and 120 seconds, typically), during which you cannot reuse that connection's "5-tuple:" the combination of {local host, local port, remote host, remote port, transport protocol}. (This timeout period is a feature of all correctly-written TCP/IP stacks, and is covered in RFC 793 and especially RFC 1122.) In practical terms, this means that if you bind to a specific port all the time, you cannot connect to the same host using the same remote port until the TIME_WAIT period expires. I have personally seen anomalous cases where the TIME_WAIT period does not occur, but when this happens, it's a bug in the stack, not something you should count on.
For more on this matter, see item 18 in The Lame List.
![]() |
Go to my home page |
![]() |
Go to my Important RFC Lists page |
![]() |
Go to the main Programming Resources page |
Please send updates and corrections to <tangent@cyberport.com>.