I needed to write an asynchronous TCP interface and quickly
discovered the windows class
CAsyncSocket. However, much searching and reading
failed to find a complete description of how it works and how to use it. Much
time and many questions flowed under the bridge in the quest to learn the basics.
The result is an application that makes it simple for me to see how this class
In this Part One I describe how class
CAsyncSocket works and
how to use it in a simple application. Part 2 presents the core code that implements the classes. It is found here.
For as long as this article is, and as difficult as it was
to find the information I needed, I was quite surprised upon realizing how
simple the basic concept is. The implementation is much easier than expected.
All Four Articles
Late Addition. This is a short summary of all four articles and a link to each.
I have completed four articles on asynchronous TCP/IP and Microsoft's class ASyncSocket. Part 1 describes the necessary concepts. Part 2 describes a single project that incorporates a server and a client in a single project and a single dialog. The user can walk through a transaction one step at a time. In parts 3 and 4 the Server and Client are separated into two projects residing in one solution. The Server and Client can run on separate computers. That project introduces the concept of multiple projects in a single solution. It introduces the concept of using source code from a separate directory. If you are not well versed in TCP/IP and with ASyncSocket, the first two articles are a must read. If you have not worked with multiple projects in one solution, or with Additional Include Directories
, Part 3 is must read. If that sentence looks weird, please read Part 3. Here is a link to each article.
Asynchronous TCP Part 1
Asynchronous TCP Part 2
AsyncsSocket Part 3: The Server
AsyncsSocket Part 4: The Client
There are many descriptions of TCP/IP operations. This
article presumes the reader understands the basics of TCP/IP operations. The
reader is also presumed to be able to create an MFC project, populate it with
buttons and other controls, make those controls do things, and display the
This is a demonstration application for
addition of all the code really needed to make it flexible and to handle any
foreseeable problem will obscure the fundamentals. It is not bullet proof.
The reader can probably find a way to crash it. This is a demonstration tool,
not a working application.
There are many applications that can work while paying
attention to primarily one thing at a time. There are many more that must pay
attention to multiple things simultaneously. There are three basic types of
- Synchronous: An application initiates something and waits for
the result. Essentially all function or methods calls are synchronous.
- Polled: An application starts something, continues work on
something else, then at a later time, returns to check on the result. Polling
consumes resources that may be needed elsewhere.
- Asynchronous: An operation initiates an operation, then does
something else while waiting for an event to trigger something else to happen,
that is asynchronous operations.
Asynchronous can be sub-divided into two or more groups.
Under the DEC (Digital Equipment Corporation) operating system VMS, the user would
initiate an operation such as I/O operation. In the calling argument would be
the address of a function to run when the I/O completes. When the I/O
operation completes the OS (Operating System) would call that function at a
slightly higher priority than the main task. That is a call back operation. It
is event driven.
In Windows, when the operation completes, the OS posts a
message to the application. Some time later when the application runs again,
the top levels of the application checks the message queue, finds that message,
then calls a method. This is also event driven, but instead of calling the
function directly, the OS sets a flag to have it called. These called methods
On*() methods you will see shortly. (Note: The wild card * is
used in the phrase
On*() to refer to multiple methods that all begin
From the perspective of this application, and probably most
applications that are like it, the difference is not visible to the user. But
they are different.
The Test Application
After reading many descriptions of how to use
CAsynchSockets, I was still at a loss as to how to use it. The result is the
MFC dialog application presented in these articles. This application does very
little, but it was the vehicle I used to assemble everything together, get them
playing well with each other, and see how they work. Here is a screen shot
taken after one message has been send from the Server to the Client.
It is a rather busy application, but asynchronous sockets are
far from trivial.
There are three groups of controls each of which has several
columns. On the left, with four sub-columns, is the Server. On the right, the
last four columns are the Client. In the middle is
C_Server_Send with three
columns. Below each of the groups is the status section.
In Server and Client sections are each divided into two sections:
- The button to initiate the action and a status field showing the
result of that button click.
- A column of
On*() counts and their counted values. For
example: The label
OnAccept() and to its right a count display,
currently set to 1 (one). We will get to this until later.
C_Server_Send group the dialog was getting crowded so
I omitted the status column. At the bottom of each section is a display of the
WSA error code. Simply put, this is the Windows status for each TCP
operation. Google it for more information. Look up that 10035 value and save
a link to your favorite web page that lists them all.
At the bottom is Received Time. After startup, the user
clicks button 6: Send and the server sends time to the client. Then
upon pressing button 7: Receive, the client captures the data and
displays it. In this case, the received time shown in HH:MM:SS.xxx. That is
all this application does.
Note the numbers in the buttons, 1 through 7. I sometimes
forgot where I was in the process so the buttons are labeled with the order of
operations. To initialize the connection between the server and client, select
buttons 1 through 5 in order. To update the time, repeat buttons 6 and 7. The
6: causes the server to send out time, the 7: causes the client
to read it. In this learning application, very little takes place
automatically. Each major step is activated with its own button. In
operational code, that must change.
The reader will eventually observe there are unused buttons
and unused display values. During the creation of this application, and from
reading various articles, I read about the various
On*() methods and their
overrides. Not understanding their meaning, I provided each one with a skeleton
method and code to count the number of times it is called.
This is my first attempt at Windows asynchronous operations
and I have decided to capture the minimal functional level. The server is
simple and does nothing but send time. The client simplicity matches the
server and does nothing but receive and display time. If you want more, you
can add it.
The reader should note that this application is a complete
TCP/IP application containing both the Server and the Client. All in one, it
talks to itself. I believe this will operate from two computers if the user
adjusts the IP addresses and runs a copy on each computer. But that is for
later. I found it simpler to do everything in one application.
In this section essentially all details of the code are
omitted and the basic operations are described. Rest assured that the key
sections of code are as simple as this description. The reader is encouraged
to reference the figures while reading this description. Keep in mind, each
major operation in the code is activated by a separate button click. To send
and received the first message, only seven clicks are required.
There are three classes in this application:
C_Server_Send_Time_Socket. All three of these derived from the Windows
CAsyncSocket. Every reference made to the base class is a
CAsyncSocket from which each class is derived. Each of these
classes is customized for its purpose, but all use the same base class.
In all TCP/IP operations there is a Server and a Client.
Generally, the server has resources that the client wants. In this demonstration
application the server has the time and sends it to the client. Nothing more.
The server side of the application instructs the class
C_Server to perform its various operations.
Begin with server button 1: Initialize. The
class tells the base class to initialize. The code really is that simple. The
CAsyncSocket handles all the details.
Button 2: Listen, puts
C_Server into a listen mode.
The base class makes the necessary Windows calls and Windows takes all the
action necessary to create a TCP port and begin waiting for a client to
connect. This is where a blocking application would stop. All other
activities would cease until the Listen operation received a response. With
async operations, the application can attend to other tasks, such as
communicating with other clients.
This is the point where I rely on the reader to understand
what has happened so far. It you do not understand these events find and read
some TCP/IP documentation, then return to this article.
Now we activate class
C_Client. In the client section
button three, 3:Initialize, does the same for the client side of
Select button 4: Connect, to send out a connect
request to the server. The code is almost that simple. Windows handles all the
details to build and send out a TCP message that finds the Server and says:
There is a Client that wants to connect to your server application.
This is the point where things become a bit difficult. That
is a bit of a miss-statement. This is where it becomes difficult to find a
I explain by digressing for a while to discuss standard
dialog operations. The creation of button, call it
Do_A, eventually results
in a method named something like:
OnButtonClickedDo_A(). When this
method is called it means that button
Do_A has been pressed. This
function is to contain the code that is to do something.
In this Server class, method
OnAccept() does not mean
that the request from the client has been accepted, it means that the
application has recognized a request from the client and the programmer must now
do something to accept that request. It means you are now ready to perform the
operation. As I read about this class the fundamental meaning of an
method shifts from
The user must understand the purpose of each method. Hopefully, this is
explained below. Now we return to this application discussion.
In this minimal application, the only thing to do is send
time from Server to Client. In your real world application, there will
probably be much to do. We will keep it simple for now.
OnAccept() method does nothing more than
increment the counter for
OnAccept() and update the display. Here is a screen
shot of the application immediately after the Client button four, 4:Connect,
has been pressed. Button 5 has NOT been clicked, only the first four buttons
have been clicked.
Note that server buttons 1 and 2 have OK next to them and
Clients 3 and 4 have OK next to them. In the Server section, field
has changed from 0 to 1 (zero to one). It has been called. The server Accept
button still has its status field set to the initial value Status. That
button has not been selected yet. Note also that in the Client section the
counter fields for
OnSend() both now display 1
(one). This simple application ignores both. However: For more advanced
applications, you will need to know that these functions have or have not been
called, and when. Eventually you probably need to learn about them, but not
It is interesting that things have happened on the Client
side, but the Server side has yet to complete its duties. You can ignore the
WSA error code for now, or look it up and discover the meaning. (Google on wsa
error 10035) Now for button five.
About the On*() Methods
Before presenting button five, the
On*() methods merit
a brief functional explanation, but the details are deferred to part 2. The
windows class ASyncSocket must be used as the base to a class you create. In
that class is a group of methods that must have over-rides. This list
There may be others that I am unaware of. In a real
application you will write code in some or all of these methods to accomplish
various tasks. In this demonstration application the code in these methods just
counts the number of times the method is called and displays it. If you use
this application to write some more test code, and when you solicit a call to
these methods, the counter will show that has happened. Adding these display fields
and the code to drive them does add a fair amount of clutter to the application,
but now the application shows which
On*() is called and when. Commercial
break is over and we return to the scheduled broadcast.
Now that we see the
OnAccept() count set to 1, we
know the time has arrived to accept the Client request. There is some
serious activity here.
More preparatory explanation is required.
A server application is seldom created to serve just one
client. It almost always has the capability to serve multiple clients
simultaneously. In this application there can be only one client, but we still
must go through the necessary motions as through there might be many.
At this point in the discussion class
performed the task of listening for the client request. The next task is to
prepare to communicate with the specific client. The third class,
is used to conduct the continuing conversation between the server and the
client. This class is implemented to send time to the client.
Back to the previous screen shot, the user has clicked
button 4 and the
OnAccept() function has been called. The counter shows
us this activity. That method’s purpose and meaning is:
A Client has initiated a connection with the Server. Now
is the time to do something about that connection.
The next step is button 5: Accept. (Don’t click it
yet.) Pressing this button calls the
C_Server Accept() method that has two
- Create an instance of
- Associate that instance with the new Client connection.
Each Server can communicate with multiple clients. For each
client, there must be one instance of class
Button 5:Accept performs these two operations. Be reminded that this
limited demonstration application can connect to only one Client.
First, a caution. In real code you will almost certainly
OnAccept() method to perform the operations that are
performed here with button 5:Accept. This demonstration application provides
the ability to step through each major operation one step at a time.
Our button 5:Accept (keep reading before clicking
it) first creates a new instance of class
line of code.) Then it goes to the base class method
Accept(), and calls
it. The argument to that call is the just created instance of class
Within the confines of the base class, Windows associates that object with the
client that just sent the Connect signal. That makes two lines of code to form
the core of the accept() method.
As a result of the
Accept() call, the new instance of
C_Server_Send_Time_Socket is connected to the client and is ready to
send data to the client. Meanwhile, if your server will connect to multiple
clients, you will be adding code to recycle
C_Server and get ready for
the next client. In this demo application, we now leave
and switch to
Prepare to Send Data to Client
Now click 5:Accept. Not much appears on the screen.
The only thing different is that under
the count for
OnSend() has incremented to 1 (one).
Again, unlike the
OnButtonClicked*() methods we are
accustomed to, this call to OnSend() does not mean that something has been
sent. It means that this instance of
C_Server_Send_Time_Socket is now
ready to send data.
Send Data To Client
In this demo application, the Client does not ask for
anything, and the Server does not send anything automatically. I considered
putting a timer in
C_Server_Send and update time every so often.
Instead I went for simple. Each time 6:Send is clicked, the time is
captured from Windows and sent to the client.
Now click 6:Send.
The results might appear a bit underwhelming, but this is
the amazing culmination of the Server side. It has sent the time to the
Client, and the
OnReceive() counter for the client has incremented to 1
(one). This time when Windows arranges to have
OnReceive() called, it
does not mean it is OK to receive data, it means that Windows has received some
data from the client and now the client can fetch, or receive that data from
In your real application you will write code in method
to capture that data and do something with it. In this demo application, we
only observe that there is some data to receive. Notice the careful choice of words.
The data sent by the Server is ready, but has not yet been received by the
BTW: The send method has one line of code to get the time, one
to get the size, and one more to send it. Three core lines of code are all
that is needed.
Get Data From Server
Now click 7:Receive. The client class goes to its
base class and calls Receive( buffer, size, flags ). This is where the
application completes the server to client data path. Now the Client has the
data and can do whatever is needed with said data. (One line of core code.)
When you do this, you will see the time update at the bottom of the dialog.
The first screen capture in this article shows the application after a data
send and receive.
Click buttons 6 and 7 to repeat the operation. Click 6
two times before clicking 7 and see how things work. Click 7:Receive
without a 6:Send. Then draw your own conclusions about what is happening
Before going on to part two read through this article a
couple of times and be certain you understand the basic concepts.