Click here to Skip to main content
13,771,804 members
Click here to Skip to main content
Add your own
alternative version


145 bookmarked
Posted 18 Mar 2013
Licenced CPOL

A Full Library for a Socket Client/Server System

, 14 Jan 2015
Rate this:
Please Sign up or sign in to vote.
My article shows a library that everyone can use to create their socket communication. Also, it explains how the library is developed.


In the course of my career, I’ve developed different socket servers in C++, Java, C# with different purposes and using different techniques. In the last 3 years, I’ve developed a socket client/server system in order to dispatch messages from multiple clients to multiple servers. I would like to share what I’ve learned with this experience and write a library to create your own message system.

The library exposes a set of abstract classes that you can quickly implement in order to create your own message system. In this way, you don’t need to know the library in depth, nor change it. The library uses I/O completion ports and the multithread pool in order to have a performance server. The library exposes a client and a server as a message within a header.


In order to allow the server to handle different clients and do something else during the receiving, the receiving is asynchronous. A BeginReceive method is called to start receiving pass a callback method and a SocketObjectState as state object for the asynchronous receiving. Then, a EndReceive method is called to get the bytes received. When the server receives a message, it fires an event. The event is fired on a different thread so as not to block the server. The ThreadPool system class is used for this scope.

When the server receives messages, the system socket uses a buffer and receives long messages with multiple reads as it can receive more messages in the same buffer if they are small and send in the same time. For that reason, the AbstractMessage exposes a static method TryReadMessage that handles all the situations. In the unit test project, you can see some unit tests on this method.

The term "socket client handler" is used to indicate the class that handles the system socket. The library includes an abstract handler that manages socket as SSL stream as well.

Using the Code

To create your own message system, you have to implement the following list of abstract classes:

  • AbstractMessageHeader defines the message header of each message
  • AbstractMessage defines the message
  • AbstractTcpSocketClientHandler defines the socket client handler
  • AbstractSocketServer defines the socket server
  • AbstractSocketClient defines the socket client

The implementation of the AbstractMessageHeader should define how the header is composed (byte to byte) and its methods to read and write the header on a buffer. The AbstractMessage’s implementation should define the kind of message header used as shown in the following code:

public class BasicMessage : AbstractMessage
    protected override AbstractMessageHeader GetMessageHeaderInstance()
        return new BasicHeader();

The other implementations are very simple if you don’t need to do something special. The class implemented from AbstractTcpSocketClient defines the message class used.

/// <summary>
/// Basic Socket Client Handler. Implements the AbstractTcpSocketClientHandler class. 
/// The message class is BasicMessage.
/// </summary>
class BasicSocketClientHandler : AbstractTcpSocketClientHandler
    /// <summary>
    /// The constructor for SSL connection.
    /// </summary>
    /// <param name="handler">The socket client handler</param>
    /// <param name="stream">The ssl stream</param>
    public BasicSocketClientHandler(Socket handler, SslStream stream)
        : base(handler, stream)
    /// <summary>
    /// The constructor for not SSL connection.
    /// </summary>
    /// <param name="handler">The socket client handler</param>
    public BasicSocketClientHandler(Socket handler)
        : base(handler, null)
    /// <summary>
    /// Return a BasicMessage empty instance.
    /// </summary>
    /// <returns>The BasicMessage instance</returns>
    protected override AbstractMessage GetMessageInstance()
        return new BasicMessage();

And finally, both of your custom client and server classes define the socket client handler class used.

protected override AbstractTcpSocketClientHandler GetHandler
   (System.Net.Sockets.Socket handler, System.Net.Security.SslStream stream)
    return new BasicClientServerLib.SocketHandler.BasicSocketClientHandler(handler, stream);

The solution includes a BasicClientServerLib project that offers a simple implementation of all the abstract classes and a simple test application.

Points of Interest

The explanation above the library is composed of the following major components:

  • Message + Message Header
  • Socket Client Handler
  • Server
  • Client

You can initialize the server using a certificate. In that way, the communication is on SSL and the client has to provide a client certification in order to be connected to the server. If you want to check the client certificate (or the server certificate), you have to write a piece of code as if you wanted to get the certificate from the windows repository and not from the file system.

When the receive callback is called, you can have in the buffer read a complete message as more complete messages as a piece of a message. The socket client handler calls the TryReadMessage method to try to read a message from the buffer. If a complete message is read, an event is fired and then the handler checks if there’re more messages in the same buffer. If the buffer doesn’t contain a complete message, the incomplete message is saved in the state object and at the next callback, the new buffer will be added to the previous buffer. You can see this part inside the TryReadMessage method.

/// <summary> 
/// Callback for asynchronous receiving.
/// </summary>
/// <param name="ar">The socket state object for receiving data</param>
private static void readCallback(IAsyncResult ar)
    SocketStateObject state = (SocketStateObject)ar.AsyncState;
    AbstractTcpSocketClientHandler handler = state.workHandler;
        // Read data from the client socket.
        int read = handler.EndReceive(ar);
        Trace.WriteLine(string.Format("Receive {0} bytes", read));
        // Data was read from the client socket.
        if (read > 0)
            // Fire event for incoming message
            while (true)
                AbstractMessage message = AbstractMessage.TryReadMessage
                                          (handler.GetMessageInstance(), state, read);
                // Fire event for received message
                if (message != null)
                    ReceiveMessageStateObject rcvObj = new ReceiveMessageStateObject() 
                                                       { Handler = handler, Message = message };
                if (state.pendingBuffer == null)
                read = 0;
            handler.socket.BeginReceive(state, new AsyncCallback(readCallback));
    catch (MessageException mex)

Therefore, the SocketStateObject is not only used to read incoming messages in an asynchronous way, but also to store the necessary information for the different situations to handle. In detail, the attribute "message" is used to save an incomplete message when the pendingBuffer is used to contain the remaining data after the first message.

internal class SocketStateObject
    public AbstractTcpSocketClientHandler workHandler = null;
    public const int BufferSize = 8192;
    public byte[] buffer = new byte[BufferSize];
    public AbstractMessage message = null;
    public byte[] pendingBuffer = null;
/// <summary>
/// Try to read a message from the buffer.
/// </summary>
/// <param name="message">The destination message</param>
/// <param name="state">The state object</param>
/// <param name="byteRead">The umber of bytes in the input buffer</param>
/// <returns>The message read, otherwise false.</returns>
internal static AbstractMessage TryReadMessage
   (AbstractMessage message, SocketStateObject state, int byteRead)
    AbstractMessage messageRead = null;
    int moreMessage = 0;
    byte[] buffer = state.buffer;     // Get buffer
    if (state.pendingBuffer != null)  //Check for pending data and merge it
        buffer = new byte[byteRead + state.pendingBuffer.Length];
        Array.Copy(state.pendingBuffer, 0, buffer, 0, state.pendingBuffer.Length);
        Array.Copy(state.buffer, 0, buffer, state.pendingBuffer.Length, byteRead);
        byteRead = buffer.Length;
    state.pendingBuffer = null;
    if (state.message == null)
        state.message = message;
        moreMessage = state.message.ReadFirstMessage(buffer, byteRead);
        Trace.WriteLine(string.Format("Receive 1st package MessageUID {0} ClientUID {1}", 
                        state.message.MessageUID, state.message.ClientUID));
        moreMessage = state.message.AppendBuffer(buffer, byteRead);
        Trace.WriteLine(string.Format("Receive more package MessageUID {0} ClientUID {1}", 
                        state.message.MessageUID, state.message.ClientUID));
    if (state.message.IsComplete())
        Trace.WriteLine(string.Format("Receive complete message {0} len {1}", 
                        state.message.MessageUID, state.message.MessageLength));
        messageRead = state.message;
             ("Prepare to receive a new message. moreMessage = {0}", moreMessage));
        state.message = null;
        if (moreMessage > 0)
            state.pendingBuffer = new byte[byteRead - moreMessage];
            Array.Copy(buffer, moreMessage, state.pendingBuffer, 0, state.pendingBuffer.Length);
               ("Copy {0} bytes to pending buffer", state.pendingBuffer.Length));
    return messageRead;

Changes on New Versions (V3)

Follow some suggestions, I've added the connection event in the client class and two new classes in the abstract library model in order to offer a version using the ReceiveAsync method instead of the Begin/End Receive.

The new classes are:

  • TcpSocketAsync – inherits from TcpSocket
  • AbstractAsyncTcpSocketClientHandler – inherits from AbstractTcpSocketClientHandler

Also, I’ve added a new test library named AsyncClientServerLib that implements a test library using the new classes.

Add New Functionalities (V4)

I have completed the library with two more functionalities:

  • Send messages with asynchronous method (SendAsync)
  • Receive messages using a queue

The first one is very useful on the server side in order to avoid possible blocks during transmission. However, a thread event is used to block a new transmission until the previous one is completed.

The second new functionality could be more useful on the client side in order to avoid too many threads and sort all the incoming messages in a queue. To realize this functionality, I have used a feature contained in .NET 4.0 (BlockingCollection), so this version cannot be used with previous .NET versions.


This article, along with any associated source code and files, is licensed under The Code Project Open License (CPOL)


About the Author

Alessandro Lentini
Team Leader Mediatech Solutions
Italy Italy
I’m an IT Project Manager for an Italian Betting Company and over the last 2 years I acquired experience in Betting area.
I have developed code in different object oriented languages (C#, C++, Java) for more than 10 years using a set of technology such as .Net, J2EE, multithreading, etc…

You may also be interested in...


Comments and Discussions

BugGreat library, possible bug Pin
Ahmed Hamdy25-Aug-16 19:13
memberAhmed Hamdy25-Aug-16 19:13 
QuestionIP from Handler Pin
Member 1028457510-Feb-16 9:05
memberMember 1028457510-Feb-16 9:05 
QuestionPerformance Pin
Deyan Timnev25-Sep-15 11:35
memberDeyan Timnev25-Sep-15 11:35 
AnswerRe: Performance Pin
Alessandro Lentini25-Sep-15 12:50
memberAlessandro Lentini25-Sep-15 12:50 
QuestionGood job but I have a problem on close connection Pin
gbataille10-Sep-15 6:53
membergbataille10-Sep-15 6:53 
AnswerRe: Good job but I have a problem on close connection Pin
Alessandro Lentini10-Sep-15 12:35
memberAlessandro Lentini10-Sep-15 12:35 
GeneralRe: Good job but I have a problem on close connection Pin
gbataille23-Nov-15 6:17
membergbataille23-Nov-15 6:17 
GeneralRe: Good job but I have a problem on close connection Pin
Alessandro Lentini23-Nov-15 6:24
memberAlessandro Lentini23-Nov-15 6:24 
QuestionThank you. Pin
Rebstorm21-Jul-15 23:29
memberRebstorm21-Jul-15 23:29 
QuestionUsing SSL? Pin
GeneralWrex16-Jun-15 18:21
memberGeneralWrex16-Jun-15 18:21 
AnswerRe: Using SSL? Pin
Alessandro Lentini18-Jun-15 23:39
memberAlessandro Lentini18-Jun-15 23:39 
GeneralRe: Using SSL? Pin
GeneralWrex18-Jun-15 23:56
memberGeneralWrex18-Jun-15 23:56 
GeneralRe: Using SSL? Pin
Alessandro Lentini19-Jun-15 0:33
memberAlessandro Lentini19-Jun-15 0:33 
GeneralRe: Using SSL? Pin
GeneralWrex19-Jun-15 0:57
memberGeneralWrex19-Jun-15 0:57 
GeneralRe: Using SSL? Pin
Alessandro Lentini19-Jun-15 1:12
memberAlessandro Lentini19-Jun-15 1:12 
GeneralRe: Using SSL? Pin
GeneralWrex19-Jun-15 1:39
memberGeneralWrex19-Jun-15 1:39 
GeneralRe: Using SSL? Pin
Alessandro Lentini19-Jun-15 1:57
memberAlessandro Lentini19-Jun-15 1:57 
GeneralRe: Using SSL? Pin
GeneralWrex19-Jun-15 2:01
memberGeneralWrex19-Jun-15 2:01 
QuestionA bugfix for AbstractMessage.cs Pin
mmcshaffry8-May-15 9:23
membermmcshaffry8-May-15 9:23 
AnswerRe: A bugfix for AbstractMessage.cs Pin
Alessandro Lentini11-May-15 1:07
memberAlessandro Lentini11-May-15 1:07 
QuestionCompatibility with PCL libraries ? Pin
abrasat5-May-15 21:33
memberabrasat5-May-15 21:33 
AnswerRe: Compatibility with PCL libraries ? Pin
Alessandro Lentini6-May-15 2:45
memberAlessandro Lentini6-May-15 2:45 
QuestionGreat job!! Have a manual? Pin
Joan Magnet10-Feb-15 22:33
memberJoan Magnet10-Feb-15 22:33 
AnswerRe: Great job!! Have a manual? Pin
Alessandro Lentini10-Feb-15 22:36
memberAlessandro Lentini10-Feb-15 22:36 
GeneralRe: Great job!! Have a manual? Pin
Joan Magnet11-Feb-15 4:05
memberJoan Magnet11-Feb-15 4:05 

General General    News News    Suggestion Suggestion    Question Question    Bug Bug    Answer Answer    Joke Joke    Praise Praise    Rant Rant    Admin Admin   

Use Ctrl+Left/Right to switch messages, Ctrl+Up/Down to switch threads, Ctrl+Shift+Left/Right to switch pages.

Permalink | Advertise | Privacy | Cookies | Terms of Use | Mobile
Web03 | 2.8.181119.1 | Last Updated 14 Jan 2015
Article Copyright 2013 by Alessandro Lentini
Everything else Copyright © CodeProject, 1999-2018
Layout: fixed | fluid