Yes. There are several listed on the Resources page, and my Examples section has several more. However, all of my current examples simply illustrate API calls and general principles, not to teach you how to start with Winsock, so you are probably better off starting with the sample programs linked in the Resources section.
Winsock proper does not provide a way for you to speak these protocols, because it only deals with the layers underneath these application-level protocols. However, there are many ways for you to get your program to speak these protocols.
Perhaps the easiest method is to use a third-party library. Section 4.1 lists several of these. Another common method is to use the WinInet library exposed by Microsoft's Internet Explorer this offers easy access to the HTTP, FTP and Gopher protocols. Finally, you can always roll your own, by reading the specifications for these protocols. Most of the Internet's protocols are documented in documents called RFCs. As far as standards go, they are generally clearly-written, though few of the standard protocols are intrinsically simple. Another of my web pages, the Important RFC Lists, links to the most commonly referenced application-level RFCs.
There are three methods, which each have advantages and disadvantages:
To get the local IP address if you already have a bound or connected socket, just call getsockname() on the socket. (By the way if you call getsockname() on a bound but unconnected socket, you will most likely get the same address you asked for when you set up the sockaddr_in structure, usually INADDR_ANY, which is 0.0.0.0.)
To get your address without opening a socket first, do a gethostbyname() on the output from gethostname(). This will return a list of all the addresses of the local host's interfaces, as shown in the example. [C++ example]
There are several problems with this method. The first is that it has problems on multi-homed machines, because gethostbyname returns all of the local machine's addresses, only one of which belongs to the interface you're interested in. (This can also be a feature, of course.)
The second problem with this method is that your machine has to have a name that the name service (such as DNS or WINS) can look up. On Windows 95 and Windows NT this is not a problem if you set up the "Host Name" field in the DNS tab of the TCP/IP protocol setup screen.
A related problem is that Windows 95 doesn't deal well with DNS and multi-homed machines. The new Dial-Up Networking 1.2 (DUN) patches help this (or is it the Winsock 2 stuff?), but they aren't foolproof. The problem is that DUN will often try to start up your dial-up adapter when you make the gethostbyname() call, because it initially tries your ISP's DNS, even though the required information is actually available locally.
The third method only works on Winsock 2. The new WSAIoctl() API supports the SIO_GET_INTERFACE_LIST option, and one of the bits of information returned is the addresses of each of the network interfaces in the system. This API is not perfect: it returns different, though usable, results on Windows 95 and Windows NT. On the other hand, it works without being connected to a host and without the aid of DNS. [C++ Example]
The short answer for clients is to use asynchronous sockets. The short answer for servers is to use blocking sockets with one thread per socket, or if you can use Winsock 2, event objects and/or overlapped I/O. The long answer is in Tutorial 1.
No, WSAStartup() fills this structure in for you.
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.
Delphi 3 and Visual Basic 5 include Winsock controls in the package. Also, Delphi and Visual Basic versions 4 and newer can talk directly to the Winsock API. Details on the latter are on Resources page.
As for other languages, it should be pointed out that some languages are "insufficiently rich" to allow you to call directly into Winsock. For example, older versions of Visual Basic (version 3 and earlier) and many scripting languages simply lack the language constructs required to make direct Winsock API calls. To use Winsock with these languages, you must use a Winsock control (e.g. an ActiveX control). The Resources page includes links to a number of these controls.
All of the socket types discussed in Tutorial 1 have some way of indicating that the connection is closed, including the situation where the remote peer closes the connection.
With asynchronous sockets (enabled with WSAAsyncSelect()), Winsock sends you an FD_CLOSE message when the connection drops. Event objects are similar: the system signals the event object with an FD_CLOSE notification.
With blocking and non-blocking sockets, you probably have a loop that calls recv() and/or send() on that socket. These functions return 0 when the connection is closed. This happens whether you explicitly close the connection or whether the remote peer closes the connection. As you would expect, if you are using select(), the SOCKET descriptor in the read_fds and/or the write_fds parameter gets set when the connection drops. As normal, you'll call recv() or send(), as appropriate, and see the 0 return value.
None of the above methods will detect abnormal connection failures. For example, if the remote host is unplugged from the Ethernet (or from the wall!), you will get no notification. My feeling is that this is a feature, because the connection might get reestablished before anyone notices, so why force everyone to restart? Additionally, Ethernet establishes no link-level connection, so there's really no way it could detect the problem anyway. By contrast, a dropped PPP link causes a detectable failure at the link layer, which might propagate up to the Winsock layer for your program to detect.
If you have a situation where you must be able to detect all network failures, you have two options, both of which require changing your protocol. The first is to redesign the protocol with a command/response structure: one side sends a command, and expects a prompt response from the other side when the command is received and/or acted upon. If the response does not arrive, the connection is assumed to be dead, or at least faulty.
The second alternative is to add an "echo" function to your protocol, where one side is expected to periodically send out an "are you still there?" packet to the other side, which it must promptly acknowledge. If the first side doesn't receive its response or the other side 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. There are other problems with ping, most notably that it's outside your protocol, so it won't tell you if the TCP connection should die and 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?
There are two main categories of tools. First, however, I would like to warn against using the SO_DEBUG option, set with setsockopt(). I have never tried it on other stacks, but on Microsoft stacks, it is ignored. I do know that Trumpet Winsock, however, offers a fairly decent debugging mode "for free" inside the tcpman tool. Trumpet (and others) may also support SO_DEBUG, though I have been unable to find any information on this. There are patched versions of Microsoft stacks floating around with some debugging support built in, but they are usually sadly outdated. You're best off with one of the other options below.
The first category is the network analyzers, colloquially known as "sniffers," probably due to an early hardware-only product by that name. Today's 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. First, software critics call a sniffer "inexpensive" when it costs less than $2000, and they positively gush when they cost less than $1000. (This is because hardware sniffers, which are still quite common, are very expensive; the Sniffer hardware analyzer from Network General costs about $15,000, for example.) There are a few truly inexpensive ones, but they all have serious limitations: some just dump the data raw to disk, others run only under uncommon operating systems like DOS and Unix, and still others are just plain weak. Another problem with sniffers is that the packets must travel over a LAN before they can capture them many sniffers won't work on a machine connected through PPP.
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 Tutorial 5 for some less-automated methods of debugging a TCP program.
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, WSAEFAULT can mean "Bad pointer passed," or "Passed buffer too small," or even "That version of the API is not supported." Since the Winsock spec documents the most likely error values that each function will return, you should use this information to construct intelligent error handlers.
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.
Note that some people will tell you that the Win32 FormatMessage() API can be coerced into returning error messages for Winsock error numbers. At best, this is undocumented behavior that only works with some implementations of Winsock. I personally have not been able to get it to work, despite significant time devoted to the problem. My advice is that you're much better off spending your time constructing meaningful error messages than chasing something that could never work very well even if it was documented behavior.
Not a thing. WSAEWOULDBLOCK is a perfectly normal occurrence in programs using non-blocking and asynchronous sockets. It's Winsock's way of telling your program "I can't do that right now, because I would have to block to do so."
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 FD_WRITE message after a failed send() call when it is safe to write; it will send you an FD_READ message when it is safe to read after a failed recv() call. Similarly, in a non-blocking sockets program that uses select(), the writefds will be set when it's okay to write, and the readfds will be set if there is data to read.
The proper sequence for closing any Winsock connection is:
Note that skipping the "optional" steps above can cause data loss.
If you are using an asynchronous socket or event objects, you may want to return to blocking mode before you execute step 3. Your application's architecture will dictate the proper choice here.
Some people will recommend that you set the SO_LINGER flag to 0 with the setsockopt() call before you call closesocket(). This is called "slamming the connection shut," and it is not a nice thing to do. It is very occasionally justifiable, but you must have fairly deep knowledge of the way TCP works before you can justify using 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.
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 I can say much more, but I'll restrain myself. CSocket is a subclass of CAsyncSocket that "fakes" blocking I/O using asynchronous sockets by running a small message pump every time it gets a WSAEWOULDBLOCK error. This is technically cute, but it has significant side effects, most of which I cover in Tutorial 1, especially the "reentrancy" issue, and issues surrounding blocking sockets in general. Plus, CSockets cause GPFs when you use them in worker threads, unless you statically link your app to MFC. Personally, I say that if you really want blocking sockets, use real Winsock blocking sockets, not this abomination.
![]() |
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>.