Multi-threaded tcp server dotnet core
| | |

Multi-threaded TCP Server using Dotnet Core Example | C#

Many times during my job as a developer I have assigned a task to Develop a Multi-threaded TCP server for handling multiple Clients. Once I developed a TCP server for Vehicle Tracker Devices & I have also developed a TCP Server for handling multiple Smart Meters.

Every time TCP Server developed using .Net Core was on top in performance as compared to other platforms. So no one should have doubt on .Net Core Performance.

Why I’m in Love With .Net Core & The Future Of .Net Core

I would also like to share a comment on one of your post which was related to handling thousands of requests using Java

The above comment describes the Dotnet Core Performance over rxjava.

Creating TCP Server

Let’s start by creating a new .Net Core Console Application Project.

I’m going to use VS Code, you may use the editor or IDE of your choice.

So create a new project using this command.

dotnet new console

Create a new file at the root of your project as Server.cs & add the below Code

using System;
using System.Net;
using System.Net.Sockets;
using System.Text;
using System.Threading;

class Server
{
    TcpListener server = null;
    public Server(string ip, int port)
    {
        IPAddress localAddr = IPAddress.Parse(ip);
        server = new TcpListener(localAddr, port);
        server.Start();
        StartListener();
    }

    public void StartListener()
    {
        try
        {
            while (true)
            {
                Console.WriteLine("Waiting for a connection...");
                TcpClient client = server.AcceptTcpClient();
                Console.WriteLine("Connected!");

                Thread t = new Thread(new ParameterizedThreadStart(HandleDeivce));
                t.Start(client);
            }
        }
        catch (SocketException e)
        {
            Console.WriteLine("SocketException: {0}", e);
            server.Stop();
        }
    }

    public void HandleDeivce(Object obj)
    {
        TcpClient client = (TcpClient)obj;
        var stream = client.GetStream();
        string imei = String.Empty;

        string data = null;
        Byte[] bytes = new Byte[256];
        int i;
        try
        {
            while ((i = stream.Read(bytes, 0, bytes.Length)) != 0)
            {
                string hex = BitConverter.ToString(bytes);
                data = Encoding.ASCII.GetString(bytes, 0, i);
                Console.WriteLine("{1}: Received: {0}", data, Thread.CurrentThread.ManagedThreadId); 

                string str = "Hey Device!";
                Byte[] reply = System.Text.Encoding.ASCII.GetBytes(str);   
                stream.Write(reply, 0, reply.Length);
                Console.WriteLine("{1}: Sent: {0}", str, Thread.CurrentThread.ManagedThreadId);
            }
        }
        catch(Exception e)
        {
            Console.WriteLine("Exception: {0}", e.ToString());
            client.Close();
        }
    }
}

Above Code Explaination:

We have a parameterized constructor taking IP & Port as parameters to instantiate a TcpListener object & start listening on the given IP & Port.

StartListener method keeps listening for incoming connections & every time when a new client gets connected, It creates a new Thread of HandleDeivce & start waiting for a new client.

HandleDeivce method receive bytes stream from the Client & reply with a message & again start listening from the client.

Calling Server.cs

Here’s my Program.cs which calls our Server.cs

using System;
using System.Threading;

class Program
{
    static void Main(string[] args)
    {
        Thread t = new Thread(delegate ()
        {
            // replace the IP with your system IP Address...
            Server myserver = new Server("192.168.***.***", 13000);
        });
        t.Start();
        
        Console.WriteLine("Server Started...!");
    }
}

Now, run you server.

you’ll see that server is listening for the clients.

If you want to Test you server, you need a client.

So, here’s the Code for Multithreaded TCP Client.

Multi-threaded TCP Client

Create a new Console Project for TCP Client & paste the below code in your Program.cs File.

using System;
using System.Net.Sockets;
using System.Threading;

class Program
{

    static void Main(string[] args)
    {
        new Thread(() => 
        {
            Thread.CurrentThread.IsBackground = true; 
            Connect("192.168.***.***", "Hello I'm Device 1...");
        }).Start();

        new Thread(() => 
        {
            Thread.CurrentThread.IsBackground = true; 
            Connect("192.168.***.***", "Hello I'm Device 2...");
        }).Start();


        Console.ReadLine();
    }

    static void Connect(String server, String message) 
    {
        try 
        {
            Int32 port = 13000;
            TcpClient client = new TcpClient(server, port);

            NetworkStream stream = client.GetStream();

            int count = 0;
            while (count++ < 3)
            {
                // Translate the Message into ASCII.
                Byte[] data = System.Text.Encoding.ASCII.GetBytes(message);   

                // Send the message to the connected TcpServer. 
                stream.Write(data, 0, data.Length);
                Console.WriteLine("Sent: {0}", message);         

                // Bytes Array to receive Server Response.
                data = new Byte[256];
                String response = String.Empty;

                // Read the Tcp Server Response Bytes.
                Int32 bytes = stream.Read(data, 0, data.Length);
                response = System.Text.Encoding.ASCII.GetString(data, 0, bytes);
                Console.WriteLine("Received: {0}", response);      

                Thread.Sleep(2000);   
            }

            stream.Close();         
            client.Close();         
        } 
        catch (Exception e) 
        {
            Console.WriteLine("Exception: {0}", e);
        }

        Console.Read();
    }
}

change the Server IP address & Port in this code according to your Server IP & Port.

Above Code will create 2 clients in separate threads & both clients will send 3 messages with the Sleep of 2 seconds after each message.

First run the Server Project then run you Client.

Let me know in comment section below If you find any problem.

Here are more Articles you might be Interested:

—  Top Open Source Asp.Net Core Content Management System (CMS)

— Best 20 .Net Core Libraries Every Developer should know

—  Creating Admin Panel in Asp.net Core MVC – Step by Step Tutorial

Similar Posts

6 Comments

  1. I’ve noticed that when sending a message larger than 256 bytes the server replies multiple times for the single message (once for each 256 chunk), and the client response text gets all messed up. This is understandable as we need to watch for the message size to be smaller than 256. Or we can make the byte[] array larger…
    But is it possible that the stream.Read(data, 0, data.Length) method will get triggered when partial message was sent by the server? If true then this could cause a lot of issues…
    The assumption in the code above is that stream.Read() gets triggered when the entire message (which is smaller 256 bytes) arrives. Is that guaranteed? Could it trigger when only part of the message arrives?

  2. It is a console application which would has to be launched. How would I make it a windows service that could start when the computer on which it is installed starts?

  3. Thank you so much, you literally saved my ass, I am new to C# and needed this to get started.

  4. That’s an awesome article ! Got it all working working on the first try (and that’s something !). In case anyone else needs to have the server be a sub-process in a .NET Core 2 web application I advise you look into the `IHostedService` interface and corresponding Microsoft documentation.

    Still, I’d like to note that it would make sense to have the `StartListener` and `HandleDeivce` methods be protected, if not private, since there is no reason to call them outside of the `Server` class itself.

    Thanks a lot for this article, you da best 🙂

Comments are closed.