Introduction

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 deep, 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.

Background

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 multiples read 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:

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.

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 details the attribute "message" is used to save an incomplete message when the pendingBuffer is used to contain the remaining data after the first message.

Changes on new versions (V3).

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

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.

Share

About the Author

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…

The difference between BasicClientServerLib and AsyncClientServerLib is that in the second one the asynchronous receiving is by ReceiveAsync method instead of the Being/EndReceive. For your purpose you can choose one of them without any problem
BR

Hello, I am new to this type of environment and it looks like your library could be a big help in getting me started. I do have a particular requirement that I am unsure how to approach, or even if your library is the right tool for the job. This is what I want to do from the client:

Connect to the remote server
Send a message
Wait for the response
Send another message
Wait for the response
Close the connection

In other words I need the get the first response before I send the next response and so on. Perhaps you could point me in the right direction?

you should create a new Send method that return the response. Inside the method you can add a semaphore (AutoResetEvent) to wait for receiving something. The receive method can set the event when receives something or better than that when it receives the response you are waiting for. So I suggest to had in the response message reference to the messageUID that was the request in order to check that.
Hope it's clear enough
BR

What issues can occur if the SendAsync() function can be called anytime (also during message reception), from an independent thread ?
For instance on the server side: while a ReceiveAsync is handled and incoming messages are processed, over the same socket data has to be sent to the client, independently of the received messages (for instance a cyclic thread on server side sends some messages to the client every couple of seconds). Can the socket instance from the SocketAsyncEventArgs object be shared for a simultaneous send/receive ? Does the socket object have to be locked ?
Or because of the buffers (set by calling SetBuffer) that cannot be shared for a "simultaneous" duplex, do I have to create anyway an own SocketAsyncEventArgs object for the sending to the client, and putting the same socket as in SocketAsyncEventArgs for the receive direction ? Examples with usage of SocketAsyncEventArgs for "real-world" duplex connections are hard to found ...

I'm so sorry to replay so late. I'm not sure to follow you. On the server side every client connection is handled by a different socket handler, therefore you shouldn't have any kind of conflict. For the send, there is a semaphore to block any new send until the previous one has been completed.
BR

If i want use the same library for .net 2.0 . As i have requirement where our application supports for .net 2.0 framework only. So how do i remove the dependency on the objects which were of .net 4.0. I tried changing to Queue but it is not working. As i am able t0 send data from client to server but not able to send data from server to client. So what will be turnaround for the code to work?

it is very nice library, but there is a question.
When you close the client and if not explicitly close the socket, the disconnect event message not been called on server side. How do I know the connection is lost in such cases?
Thanks!

Hi, I'm sorry to reply so late. I'm not sure to understand the question. If the network connection is closed for any reason the event closeConnectionEvent is raised in the socket server class. Do you find a specific case for which the connection is broken and the event is not raised, please ?
However, please consider that in some situation it could be possible that some network device "keep" the connection open. I mean that until you try to send a message you don't realise that the connection has been closed.

I also have a question client disconnection with the asynchronous approach. If a socket is not closed properly by an application (for instance the network cable is pulled out somewhere on the way between client and server), no events are generated.
For such cases usually a kind of cyclic send of keep-alive messages is used to detect network disconnection (a synchronous send over a socket detects immediately a network disconnection). What about the SendAsync() method, how can in this case a network failure be detected, to get same functionality as for the synchronous socket "send" ?

I'm sorry to reply so late. The disconnection event depends of the HW used in the NW. I experienced that we same kind of disconnection could be detect or not and it seems related to how the NW is configured. I agree with you that a keep alive message could be useful, but on my eyes it's on a upper level than my library, let me say an application level.
BR

I have some question about reading messages. In my small CTI system i am going to send message from server to clients and the size of messages will not be more than 1000-1500-2000 bytes. What should I do in order to not implement TryReadMessage in ReadCallback. Really i need to read my message without state object. You know. Or I can not change this behavior? I would like to delete from my project such method as TryReadMessage, AppendBuffer. What should i write in ReadCallback method instead of TryReadMessage. Thank you very much for the answer!

I'm not so sure if I've understood your question. But please let me say a couple of things that maybe can help you.
The read operation is asynchronous, that's why you need a state object. TryRedMessage works fine with small message too. I agree that you don't need to handle the case that a message is received in 2 blocks, but you can keep the code. However, if you want to remove this part, you should change the TryReadMessage considering you always will have state.message = null in this block