<< |
Winsock Programmer's FAQ |
>> |
2.1 - Are there any sample apps on the Net?Yes. There are several listed on the Resources page, and the FAQ's Examples section has several more. If you're just getting started with Winsock, you may be especially interested in these samples. 2.2 - Do I need to initialize the WSAData structure before calling WSAStartup?No, 2.3 - I'm getting link errors when compiling Winsock programs. What's wrong?You're most likely not linking with the proper Winsock import library. For 16-bit Windows systems, this is winsock.lib. For 32-bit Windows systems using Winsock 1.1 functions only, it is wsock32.lib. And for programs needing Winsock 2 support, you need to link with ws2_32.lib. 2.4 - If I write a Winsock program, will I be able to communicate with a Unix sockets program?Absolutely! This common question is the result of confusing protocols with the APIs. Communicating programs need not have been created with the same APIs, as long as they are using the same transport and network protocols. 2.5 - Can I use Winsock with { My Favorite Language }?Most programming languages these days have some way of accessing Winsock, but Winsock is rarely used directly except from C or C++. There are several reasons for this. Reason 1: Some languages simply lack the language features to call the Winsock API. Your language needs the following to fully use the Winsock API:
Reason 2: Many languages rely on some form of component architecture (e.g. ActiveX) to provide outside services like network access. Often the language environment comes with basic networking components, sufficient for most tasks. If your tool didn't come with the necessary compnents, or the ones it does come with aren't powerful enough, you may be able to find the functionality you need in a third-party library, rather than writing the necessary Winsock code yourself. Reason 3: Many newer languages For these reasons and others, this FAQ is biased towards C++. If your language allows direct access to the Winsock API, you may be able to translate the C++ code in the FAQ into equivalent code in your chosen language. However, I recommend that you look for sample code in your chosen language via the Web Pages section of the FAQ, so you can study working code before you begin translating. 2.6 - Are there any tools available for debugging Winsock programs?First, I would like to warn against using the built-in Winsock debugging options, SO_DEBUG and the dt_dll.dll. It'd be nice if these worked, but as this article explains, it's currently so much of a mess that the tools below work better for most people. There are two categories of debugging tools: network analyzers (colloquially known as "sniffers") and Winsock shims.
Sniffers are usually software packages that run on one of the LAN's workstations and, due to the way typical LANs work, capture all of the traffic going over the LAN. Good sniffers will also decode that traffic by various degrees. One advantage of a sniffer is that it literally sees everything about the conversation, including low level protocol details that aren't available from the Winsock layer. Another is that the good ones are extremely powerful and configurable. For example, some allow you to write "protocol plugins" that will decode any protocol (such as a custom protocol that you've developed). The disadvantages of sniffers are several:
All that aside, however, sometimes a sniffer is the only way to find out what you want to know about your program's behavior. If you've got the cash, a good sniffer is almost always the best tool for the job. The other tool category is "Winsock shims." A shim sits between your program and Winsock, either by replacing the DLL itself with a proxy DLL, or by "hooking" the Winsock DLL's API. These tools are limited to monitoring events on the Winsock layer itself, and can only monitor traffic to or from a single host. (That is, they can't see the "big picture" of simultaneous conversations between many machines.) Their advantages are that this is usually sufficient, and that the most expensive shims cost less than $200. The Debugging Resources page has links to several good sniffers and shims. Also, see Debugging TCP for some less-automated methods of debugging a TCP program. 2.7 - How do I get a readable error message from a Winsock error number?The problem with this question is that it assumes that there is a
"good" canned error message for every situation. The reality is that many
times, you need to know the program's context before you can turn an error
value into a meaningful error message. For example, Still, sometimes an API call returns something unexpected, so a cryptic error message is better than none at all. In that case, you can just build a stringtable in your resource file mapping error numbers to error messages. There is one such RC file for the Winsock 1.1 error values available here. Alternately, the basic Winsock tutorial programs in the FAQ include a utility module (ws_util.cpp) that defines a function for translating Winsock error numbers into strings. Note that some people will tell you that the Win32
2.8 - Winsock keeps returning the error WSAEWOULDBLOCK. What's wrong with my program?Not a thing. The next question is, how do you know when it's safe to try
again? In the case of asynchronous sockets, Winsock will send you an
Note that Win9x has a bug where
2.9 - What can you tell me about MFC's CSocket and CAsyncSocket?CAsyncSocket is a not-particularly-fancy asynchronous sockets wrapper. I guess it makes using the asynch Winsock API slightly easier, but I personally prefer smarter wrappers that offer features like buffering. (The same commentary applies to OWL's TSocket class. I have no idea what VCL's socket library looks like, so I can't comment on it.) I suggest that if you want to use a Winsock wrapper, try some of the offerings linked on the Libraries page. I personally use my own Endpoint library, which is freely available, is much smarter than both OWL or MFCs offerings, and is compatible with either class library. See the Libraries page for details. As for CSocket, all I can say is ick. No, that's not true
2.10 - How can I test my Winsock application without setting up a network?There is a special address called the loopback or localhost address, 127.0.0.1. This lets two programs running on a single machine talk to each other. The server usually listens for connections on all available interfaces, and the client connects to the localhost address. (See the Examples section for basic client and server program code.) If you have Internet access from your development machine, you're already set up for this. If you don't, you can try installing Dial Up Networking and pointing
it at an unused serial port. This can be quirky, but it's possible
to limp by with this method. The main problems are when DUN decides
it needs to dial the modem, and finds that there is no modem on the
port you chose. To minimize this problem, never use name lookup calls
like Be warned: behavior through the loopback interface may well be different from behavior on a network, if only because conditions are much simpler within a single machine than over a LAN or WAN. You should try to test your application on a real network, even if you do primary development on a single machine. 2.11 - What's the proper way to close a TCP socket?The proper sequence for closing a TCP connection is:
Skipping the first and third steps above can cause data loss. Nonblocking or asynchronous sockets complicate the first and third steps. You can either build "finish sending/receiving" logic into your normal I/O loop, or you can temporarily put the socket in blocking mode and do the last bits of I/O that way. The proper choice depends on your program's architecture and requirements. 2.12 - Is it possible to close the connection "abnormally"?Sure, but it's an evil thing to do. :) The simplest way is to set the
"Slamming the connection shut" is only justifiable in a very small number of cases. You must have fairly deep knowledge of the way TCP works before you can properly decide to use this technique. Generally, the perceived need to slam the connection shut comes from a broken program, either yours or the remote peer. I recommend that you try to fix the broken program so you don't have to resort to such a questionable technique. 2.13 - How do I detect when my TCP connection is closed?All of the I/O strategies discussed in the I/O strategies article have some way of indicating that the connection is closed. First, keep in mind that TCP is a full-duplex network protocol. That means that you can close the connection half-way and still send data on the other half. An example is a web browser: it sends a short request to the web server, then closes its half of the connection. The web server then sends back the requested data on the other half of the connection, and closes its sending side, which terminates the TCP session. Normal TCP programs only close the sending half, which the remote peer perceives as the receiving half. So, what you normally want to detect is whether the remote peer closed its sending half, meaning you won't be receiving data from them any more. With asynchronous sockets, Winsock sends you an With blocking and non-blocking sockets, you probably have a loop that
calls As you might have guessed from the discussion above, it is also possible to close the receiving half of the connection. This won't stop the remote peer from sending you data, but it will stop Winsock from telling you about it. Winsock may just silently drop the data on the floor, or it may send an error back to the remote peer. See below for information on handling abnormal disconnects. 2.14 - How do I detect an abnormal network disconnect?The previous question deals with detecting when a protocol connection is dropped normally, but what if you want to detect other problems, like unplugged network cables or crashed workstations? In these cases, the failure prevents notifying the remote peer that something is wrong. My feeling is that this is usually a feature, because the broken component might get fixed before anyone notices, so why force everyone to restart? If you have a situation where you must be able to detect all network failures, you have two options: The first option is to give the protocol a command/response structure: one host sends a command and expects a prompt response from the other host when the command is received or acted upon. If the response does not arrive, the connection is assumed to be dead, or at least faulty. The second option is to add an "echo" function to your protocol, where one host (usually the client) is expected to periodically send out an "are you still there?" packet to the other host, which it must promptly acknowledge. If the echo-sending host doesn't receive its response or the receiving host fails to see an echo request for a certain period of time, the program can assume that the connection is bad or the remote host has gone down. If you choose the "echo" alternative, avoid the temptation to use the ICMP "ping" facility for this. If you did it this way, you would have to send pings from both sides, because Microsoft stacks won't let you see the other side's echo requests, only responses to your own echo requests. Another problem with ping is that it's outside your protocol, so it won't detect a failed TCP connection if the hardware connection remains viable. A final problem with the ping technique is that ICMP is an unreliable protocol: does it make a whole lot of sense to use an unreliable protocol to add an assurance of reliability to another protocol? Another option you should not bother with is the TCP keepalive mechanism. This is a way to tell the stack to send a packet out over the connection at specific intervals whether there's real data to send or not. If the remote host is up, it will send back a similar reply packet. If the TCP connection is no longer valid (e.g. the remote host has rebooted since the last keepalive), the remote host will send back a reset packet, killing the local host's connection. If the remote host is down, the local host's TCP stack will time out waiting for the reply and kill the connection. There are two problems with keepalives:
Note that different types of networks handle physical disconnection differently. Ethernet, for example, establishes no link-level connection, so if you unplug the network cable, a remote host can't tell that its peer is physically unable to communicate. By contrast, a dropped PPP link causes a detectable failure at the link layer, which propagates up to the Winsock layer for your program to detect. 2.15 - How can I change the timeout for a Winsock function?Some of the blocking Winsock functions (e.g. Under Winsock 2, you can set the Unfortunately, the Winsock spec does not document a way to change many other timeout values, and the above advice doesn't apply to Winsock 1.1. The solution is to avoid blocking sockets altogether. All of the non-blocking socket methods lend themselves to timeouts:
Note that with asynchronous and non-blocking sockets, you may be able to avoid handling timeouts altogether. Your program continues working even while Winsock is busy. So, you can leave it up to the user to cancel an operation that's taking too long, or just let Winsock's natural timeout expire rather than taking over this functionality in your code. |
<< General Winsock Information | Intermediate Winsock Issues >> |
Last modified on 29 April 2000 at 15:52 UTC-7 | Please send corrections to tangent@cyberport.com. |
< Go to the main FAQ page |
|
<<< Go to my Home Page |