This article presents a set of classes that are useful for client/server communication.
These classes can be used in Win32 or MFC apps, and include Unicode support.
This article is based on Liyang Yu's excellent classes, which can be found
Porting to MFC and Unicode
Yu's original classes already supported Win32, but not Unicode. To be able to use
these classes in both MFC and Win32 apps - either Unicode or ANSI - meant that
variables and parameters had to be examined, and where necessary, converted
parameters. Of course,
corresponding changes were required for string functions - e.g., converting
char variables were converted. Some functions still
require use of
char, because Winsock API is based on ANSI. Example:
There are five main classes:
ssmcException - captures and reports errors.
ssmcHostInfo - if you pass a host name to constructor, this class will
tell you IP address, and if you pass in an IP address, it will tell
you host name.
ssmcSocket - this class encapsulates socket-related API calls into a
generic socket class. The derived class
ssmcThread - this is a generic class that includes APIs to create and execute a thread.
ssmcThreadData - main purpose of this class is to encapsulate data that
thread needs. The derived classes
ssmcServerThreadData wrap data needed by server's client and server threads.
Concepts and Facilities
Yu has already described classes in his
so I will focus here on how to use these classes in sample apps.
The data and control flow of socket-based systems is shown in following figure:
In client and server demo apps, messages are null-terminated strings.
However, any type of data, including binary data, may be sent by these classes;
of course, both client and server must understand data format.
In demo apps, client prepends each message with its thread ID.
The server app expects this thread ID to be present, and removes it before echoing
message back to client.
function, following steps are performed:
Initialize Winsock library:
Create server socket on local host:
m_pServer = new ssmcTcpSocket(PORTNUM);
Create a server thread to implement server processing: listen to socket,
accept client calls and communicate with clients. This will free the
main thread to do other processing.
m_pServerData = new ssmcServerThreadData(m_pServer, serverName);
ssmcThread* pServerThread = new ssmcThread(ServerThread, (void*)m_pServerData);
ServerThread() processing is diagrammed in following figure:
In server thread, a new client thread is created each time
server accepts a new client. The client thread processing
is diagrammed in following figure:
The final thing
Startup() function does is start a timer that will
check for active clients and display count on server dialog.
The above steps are diagrammed in following figure:
Now that server thread has started, server is ready to accept new
The server app initially looks like this:
When user clicks Connect
button, client app's
function is called:
button is now enabled. When it's clicked,
message is sent to server, which will echo it back to client:
After user connects and sends a message, client app
looks like this:
and server app looks like:
Detecting Client Disconnect
A client might disconnect from server programmatically or because a
program fault causes client app to exit. For either case,
function will detect disconnect,
flag to true, and exit thread.
When it detects a client disconnect, server app looks like:
Detecting Server Disconnect
Unlike server app, client app is usually not doing a
and so detecting when server disconnects involves some extra work.
In client app, this involves implementing a "ping" facility, where the
client periodically sends a "ping" message to server.
When it detects a server disconnect, client app looks like:
Notice that ping checkbox
Sending Multiple Messages
The client app has been set up to allow more than one message to be sent.
Each message includes a message number, so echoed message can be verified.
ANSI Clients and Unicode Clients
The demo project has both ANSI and Unicode build configurations.
Regardless of whether server is ANSI or Unicode, it will correctly read
and send messages. This works because a Unicode client prepends a
Unicode header (B
ark, or BOM
to each message it sends. The server sees this BOM, and 1) interprets the
message text as Unicode; and 2) sends back a Unicode message, with BOM.
Obviously, this works fine for demo, because messages are always
Using BOM technique, a Unicode server can handle both ANSI and
Unicode clients; and so can an ANSI server (try it and see).
According to Unicode Consortium (see
UTF & BOM
signature at beginning of certain data streams (such as unmarked
plaintext files). is referred to as the BOM character, for
Byte Order Mark. For little-endian systems such as those
based on Intel x86 processors, the BOM is encoded as the
two byte sequence FF FE (hex values). For big-endian systems,
the BOM is FE FF. Where a BOM is useful is with files that
are typed as text, but not known to be in either
big- or little-endian format. In that situation, BOM serves
both as a hint that the text is Unicode, and also what type
of byte-ordering was used to create the text.
How To Use
To integrate ssmc classes into your server app, you need
to add following files to your project:
To integrate ssmc
classes into your client app, you need
to add following files to your project:
Both client and server need to be linked to XWSAError.lib,
and XWSAError.dll needs to be in exe's directory
when app is run.
For details on how to use ssmc classes, refer to code
in mfc clientDlg.cpp and mfc serverDlg.cpp.
Version 1.0 - 2005 January 26
This software is released into the public domain. You are free to use
it in any way you like, except that you may not sell this source code.
If you modify it or extend it, please to consider
posting new code here for everyone to share. This software is provided
"as is" with no expressed or implied warranty. I accept no liability
for any damage or loss of business that this software may cause.