Winsock Programmer’s FAQ
Basic Winsock Examples: Asynchronous I/O Client
This example is based on the "MFCConsole" framework. Between that base and the FAQ-specific extensions, there are 1800 lines of generic framework code, neatly separated from the specific parts of each example based on it. You do not need to understand this framework to learn from the examples, but if you are interested, you can find information about the framework on the MFCConsole page.
The example framework has two main menu items: "Start Winsock Handler"
(Ctrl-W), and a generic "Action" item (Ctrl-A). When you give the
Start command, it calls
DoWinsock() — this is similar to
the console programs'
DoWinsock() mechanism. The main difference
in the GUI version is that
DoWinsock() doesn't call the network
handling functions directly: it just creates the object that does the
real work. Then you give the Action command to do whatever specific
thing the example does.
The unique parts of this example are in the CAsyncClientWnd class. That class derives from CNetworkDriver, a generic interface that the framework calls when you give the Start and Action commands mentioned above.
Start() function in this example looks up the server's
address and establishes the network connection to the server. Then the
Action() function sends a packet for the server to echo back,
and reads/verifies the reply. If the Action command is given again,
another send/read sequence occurs. Then when the user closes the window,
the connection is gracefully shut down.
That's more or less what the simpler basic blocking client does. The tricky bit, though, is that Winsock never blocks when all of this is going on. Whenever Winsock can, it does what we ask it to immediately, but most everything on the network takes time. So, rather than stop the program to wait on the network, Winsock lets us go back to handling the UI while it waits for the network operation to complete. When it does, Winsock sends us a window message to tell us the result. This means we can handle both networking and the UI in a single thread, but it does make the program harder to write.
Here's a detailed breakdown of the run sequence:
DoWinsock(), which creates CAsyncClientWnd, the window object that contains the async client code.
CNetworkDriver::Start(), which our subclass overrides. It just saves the address and port given, and does a DNS lookup on the address. The lookup almost always takes some time, so we usually just exit
Start()without actually opening the connection to the server.
OnWinsockLookup()message handler. If it was a successful lookup, we call
EstablishConnection()creates the socket, marks it as an asynchronous I/O socket, and attempts the connection. Again, this almost always takes some time, so we exit without having connected, and wait for Winsock to tell us whether it could connect or not.
OnWinsockNotify()message handler. This is the core of the asynchronous I/O handling: this message handler gets called for connections, disconnections, "data ready to read" events, and "okay to write" events. It also gets called for errors that happen asynchronously, like "connection refused by server". This time through, we get an FD_CONNECT notification, which just causes us to print a message saying that we're connected. Notice that we also get an FD_WRITE notification, which simply means Winsock is ready to handle
SendEcho()function isn't as smart as it might be: it's possible for
send()to only queue up part of the buffer we give it. It's much rarer than the similar case with
recv()but it can happen.)
shutdown()only starts the shutdown process: we have to wait for an FD_CLOSE notification to know that the connection is really shut down. Meanwhile, we ignore window close requests.
This client program has about 330 lines of code, compared to about 150 in the basic blocking client. That's the tradeoff for getting a program that handles both the GUI and the network in a single thread without either blocking the other.
The project package (33 KB) is a complete Visual C++ 5.0 project. It includes everything you need to build the sample.
Note that this example program is released under a different license than the other example programs. It's a BSD-style license, which means you can do anything you want with the example so long as you don't sue me or my employer. Not even if it prints 500 pages of personal insults on your customer's high-speed laser printer.
<< Basic Blocking Client
||CAsyncSocket-based Client >>|
|Updated Mon Sep 22 2008 12:15 MDT||Go to my home page|