Click here to Skip to main content
11,638,351 members (76,613 online)
Click here to Skip to main content

Scalable UDP Client Server

, 25 Dec 2014 CPOL 77.1K 3.4K 67
Rate this:
Please Sign up or sign in to vote.
Architecture of UDP server application.

 

Introduction

This article is about a scalable UDP socket server program. This program uses Async Socket methods to support communication with multiple clients. The server is designed in a way that it will isolate receive and send functionality. In this program there is also provision to process your data in individual threads. In any case the server will not stop listening. I have built the skeleton that will provide only the architecture where you can use your business logic for development.

Note:- This is a pattern using you can implement the more scalable UDP Server. In case you need more assistance please do write in comments section.

Background

Our client has real time devices fixed on properties for security. This device is capable of intruder detection and fire smoke detection. There are nearly 5000 devices present all over the country. The device contains a SIM card for the communication. It uses GPRS via the UDP communication protocol. These devices needs a communication rooter which provides understandable information for third party systems.

My requirement was to integrate my application with these devices. Due to the high number of clients I needed to develop a server which could manage communication concurrently with multiple devices. The devices need to be communicated to once it starts sending messages. The device starts communication only under a condition: if any of the sensors is activated and triggers the device.

Once the device gets triggered in any of the events, devices start sending signals to the server. The server’s responsibility is to respond to these requests and gather data from the device .Then assemble that information and produce the required output.

To develop this type of application, performance is very critical. The reason for criticality is that all communication to the server is on only one port. We have to manage each and every byte very carefully so it can serve as many devices as possible at a time. The pick time of device calling is morning 8 to 9. Each device has an individual IP and port which communicates on only one port of the server.

Process

To develop this application my starting requirement was to establish communication between devices and the server. This is not a difficult problem, I just need to configure the server with an open IP to communicate with the device. The data retrieved from the device is very critical and requires a CRC check. We need to maintain data information in the trace log for each device.

With this requirement my first thought was how many concurrent devices we can support. I did research on the communication mode. First I used the Winsock control. The reason for using Winsock is that I was able to send a response to the device. The problem with Winsock is that it is a very heavy object and in the case of a time out, the connection gets disconnected and Winsock sits idle and will not respond to the device. To resolve this problem I found out that I can dispose Winsock and then recreate it. That works but again the time constraint is there.

Then I did some research on the System.Net.Sockets.Socket class. Socket works fine with the device. The good news is Socket supports async communication. One of the advantages about UDP is that it never blocks sending and saves us multiple ports for communication on the server. The socket BeginRecieve() and BeginSendTo() methods are used to manage async calls with different devices.

The calls are multiple with the same device because of the data we need to get in multiple chunks. Multiple devices are calling at the same time so we need to keep track of each and every request and reply on the correct device. In case data does not arrive in the defined timeline we need to implement a retry strategy. I used four components in this project.

  • GUI will display the on-going process events happening in the application.
  • The Data Collector class holds data for processing.
  • Data process class processes data.
  • Utility functions.

This approach gives me isolation of send receive information and increases response time for the server.

Environment Diagram

The devices communicate via a SIM card to our Session Manager. Once the data is received into the session manager the data is passed to the processing unit. The processing unit contains the data collector and data process modules which has the functionality of handling the data. The session manager is an intelligent unit which is able to manage the traffic of incoming and outgoing data.

 

Using the code

The project is divided into four parts.

  • UDP.Server
  • UDP.Server.Utils
  • UDP.ServerComponents
  • UDP.ServerCore

Here are the details:

  • UDP.Server: This is the starting point of the application. The work of the UDP.Server library is just a part of the View, the traffic, and traffic related events.
  • UDP.ServerCore: This is the main core of the project. The functionality listed below should be present in this module:
    • Manage send receive data packets of UDP.
    • Act as a router for packets to correct data collector container.
    • Once data is collected pass it to the proper process module.
    • Clean up the data object once the data is processed.
    • Send notification to the server UI.
  • UDP.ServerComponents: Secure pass components contain the structure of the data which you need to process. Like an entity class you can create structure, class, or enumeration in this class. In these components there should not be any business logic present. They should only contain the structure. For example, email structure. If you want to send email, create an email structure class. Create an instance of the class and use it wherever you need.
  • UDP.Server.Utils: As per the name I have used this project for all utilities. For FTP connectivity, CRC calculation, and other common functionality I am putting in this project.

In this project you will only get the skeleton of the project you need to implement your code as per your requirements.

The class SessionManager is the core of the program. SessionManager’s responsibilities are:

  • Start and stop the server.
  • Receive and send data on UDP.
  • Start processing thread to process data.
  • Determines data is passed to the correct data collector.

The class SessionManager is used to manage communication related stuff. The Socket gets initialized when the SessionManagers object is instantiated.

private Socket _UdpSocket;
 
/// <summary>
/// Initialize socket 
/// </summary>
private void InitializeUdpSocket()
{ 
    _UdpSocket = new Socket(AddressFamily.InterNetwork,
    SocketType.Dgram, ProtocolType.Udp);
}

Below code is for starting the listener. This function starts receiving UDP traffic. UpdateUI is the callback method which will notify the GUI what data we have received.

public delegate void UpdateUIDelegate(object value);
  public event UpdateUIDelegate UpdateUI;
 
 /// <summary>
/// Start listener
/// </summary>
public void StartListener()
{        
    //Assign the any IP of the machine and listen on port number 52200
    _ReceiveByteData = new byte[1072];
    _UdpSocket.Bind(new IPEndPoint(IPAddress.Any, Int32.Parse(
       SPConfigVal.GetConfigValue(SecurePassConstants.ServerPort))));
    EndPoint newClientEP = new IPEndPoint(IPAddress.Any, 0);
    //Start receiving data
    _UdpSocket.BeginReceiveFrom(_ReceiveByteData, 0, _ReceiveByteData.Length,
    SocketFlags.None, ref newClientEP, DoReceiveFrom, _UdpSocket);
    if (UpdateUI != null)
    {
         UpdateUI(CommonFunctions.GetDateTime() + " Server Stated....");
    }
}

The DoReceivedForm method is used as async and receives traffic from multiple Devices. Once data is received it transfers data to the collection container. Once data is collected the class returns data for the next request and sends the request as soon as possible. The reason behind this fast process is we need to keep the server ready for new incoming requests.

/// <summary>
/// socket call back function to receive message from clients
/// </summary>
/// <param name="ar"></param>
private void DoReceiveFrom(IAsyncResult ar)
{
    try
    {
        Socket recvSock = (Socket)ar.AsyncState;
        EndPoint clientEP = new IPEndPoint(IPAddress.Any, 0);
        int msgLen = recvSock.EndReceiveFrom(ar, ref clientEP);
        byte[] objbuffer = new byte[msgLen];
        Array.Copy(_ReceiveByteData, objbuffer, msgLen);
        _ReceiveByteData = null;
       //notification of the data on UI
        if (UpdateUI != null)
        {
            UpdateUI(objbuffer);
        }
         _SendByteData = ProcessDeviceData(objbuffer, clientEP);
         SendData(clientEP, _SendByteData);
     }

The request accepted by the device is a 16 byte header. It contains instructions which my application needs. The processDeviceData function returns the request for the next information.

Components of the application ISession is the data collector root class. IsessionStatusCall and IsessionVideoWakeup are the sub components for the StatusCall and Videowakeup calls. IDeviceDataHandler is a root for the data process class. IStatusChangeDeviceDataHandler, IVideoWakeupDeviceDataHandler are sub interface for video and status. If you look at the code you will find the use of these classes. Using these strategy patterns, we can achieve device traffic communication.

interface ISession
interface ISessionStatusCall : ISession
interface ISessionVideoWakeup:ISession
interface IStatusChangeDeviceDataHandler : IDeviceDataHandler
interface IVideoWakeupDeviceDataHandler : IDeviceDataHandler

The Socket.IOControl Property plays very vital role in performance.

ICMP unreachable error occurs when a router receives a datagram that requires fragmentation, but the “don't fragment” (DF) flag is turned on in the IP header. This error can be used by a program that needs to determine the smallest MTU in the path to a destination-called the path MTU discovery mechanism

Below is the code to avoid this problem.

public const int SIO_UDP_CONNRESET = -1744830452;

Then set the low level io control to ignore these messages:

 

var client = new UdpClient(endpoint);
client.Client.IOControl(IOControlCode)SIO_UDP_CONNRESET,
new byte[] {0, 0, 0, 0 },null);

 

Points of Interest

While writing this code I learnt that you can write a UDP server which is capable of handling multiple requests on one port. The benefit of using UDP is that it is state less so there is no problem of managing ack info. The data trace log functionality is also used for writing the received data after processing. The fun thing about UDP is some times you need to ask data twice from the Device and UDP will give you two data packets: one which we asked previously and one which you asked after that.

License

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

Share

About the Author

Preetam U Ramdhave
Technical Lead
India India
No Biography provided

You may also be interested in...

Comments and Discussions

 
QuestionInteresting Pin
Rob Philpott14-Jan-15 4:59
professionalRob Philpott14-Jan-15 4:59 
AnswerRe: Interesting Pin
Preetam U Ramdhave9-Feb-15 1:37
memberPreetam U Ramdhave9-Feb-15 1:37 
QuestionUDP Server GPS Pin
rockford3336-Aug-14 3:16
memberrockford3336-Aug-14 3:16 
AnswerRe: UDP Server GPS Pin
Preetam U Ramdhave11-Aug-14 1:51
memberPreetam U Ramdhave11-Aug-14 1:51 
QuestionI vote you 5 Pin
WuRunZhe15-Jun-14 20:12
memberWuRunZhe15-Jun-14 20:12 
QuestionUDP Connection Dropout\Reconnection Pin
gemmtech1-Nov-13 6:53
membergemmtech1-Nov-13 6:53 
AnswerRe: UDP Connection Dropout\Reconnection Pin
Preetam U Ramdhave14-Nov-13 1:25
memberPreetam U Ramdhave14-Nov-13 1:25 
QuestionUnderstanding the processing thread Pin
Fred Barrett30-May-13 8:04
memberFred Barrett30-May-13 8:04 
AnswerRe: Understanding the processing thread Pin
Preetam U Ramdhave30-May-13 20:57
memberPreetam U Ramdhave30-May-13 20:57 
GeneralGreat work! Pin
teapot200629-May-13 5:12
memberteapot200629-May-13 5:12 
GeneralRe: Great work! Pin
Preetam U Ramdhave29-May-13 7:53
memberPreetam U Ramdhave29-May-13 7:53 
GeneralRe: Great work! Pin
teapot20066-Jun-13 3:50
memberteapot20066-Jun-13 3:50 
QuestionUseful Article Pin
Prasad Khandekar24-May-13 0:57
professionalPrasad Khandekar24-May-13 0:57 
QuestionVery Good Research Pin
reymond24-May-13 0:10
memberreymond24-May-13 0:10 
AnswerRe: Very Good Research Pin
Preetam U Ramdhave24-May-13 1:12
memberPreetam U Ramdhave24-May-13 1:12 
QuestionDownload source code Pin
Member 938620013-Apr-13 4:44
memberMember 938620013-Apr-13 4:44 
AnswerRe: Download source code Pin
Preetam U Ramdhave13-Apr-13 17:43
memberPreetam U Ramdhave13-Apr-13 17:43 
AnswerRe: Download source code Pin
Preetam U Ramdhave20-May-13 1:28
memberPreetam U Ramdhave20-May-13 1:28 
Generalvery useful Pin
zheng shuo26-Feb-13 1:42
memberzheng shuo26-Feb-13 1:42 
GeneralRe: very useful Pin
Preetam U Ramdhave26-Feb-13 6:22
memberPreetam U Ramdhave26-Feb-13 6:22 
QuestionHave you run into any memory issues? Pin
Aron Weiler25-Feb-13 20:12
memberAron Weiler25-Feb-13 20:12 
AnswerRe: Have you run into any memory issues? Pin
Preetam U Ramdhave25-Feb-13 21:19
memberPreetam U Ramdhave25-Feb-13 21:19 
GeneralRe: Have you run into any memory issues? Pin
Aron Weiler26-Feb-13 11:32
memberAron Weiler26-Feb-13 11:32 

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

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

| Advertise | Privacy | Terms of Use | Mobile
Web03 | 2.8.150728.1 | Last Updated 26 Dec 2014
Article Copyright 2014 by Preetam U Ramdhave
Everything else Copyright © CodeProject, 1999-2015
Layout: fixed | fluid