Help with event driven TCP server

10,338

Solution 1

Here is a server skeleton for what you might need. No exceptions are handled.

class Program
{
    public static ManualResetEvent connected = new ManualResetEvent(false);

    static void Main(string[] args)
    {
        string ip = "127.0.0.1";
        int port = 14500;

        TcpListener server = new TcpListener(IPAddress.Parse(ip), port);
        server.Start();

        Console.WriteLine("Server started...");

        while (true)
        {
            connected.Reset();
            server.BeginAcceptTcpClient(new AsyncCallback(AcceptCallback), server);
            connected.WaitOne();
        }
    }

    public static void AcceptCallback(IAsyncResult ar)
    {
        TcpListener listener = (TcpListener)ar.AsyncState;
        TcpClient client = listener.EndAcceptTcpClient(ar);

        byte[] buffer = new byte[1024];
        NetworkStream ns = client.GetStream();
        if (ns.CanRead)
        {
            ns.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(ReadCallback), new object[] { ns, buffer });
        }

        connected.Set();
    }

    public static void ReadCallback(IAsyncResult ar)
    {
        NetworkStream ns = (NetworkStream)((ar.AsyncState as object[])[0]);
        byte[] buffer = (byte[])((ar.AsyncState as object[])[1]);
        int n = ns.EndRead(ar);
        if (n > 0)
        {
            Console.WriteLine(Encoding.ASCII.GetString(buffer, 0, n));
        }
        ns.BeginRead(buffer, 0, buffer.Length, new AsyncCallback(ReadCallback), new object[] { ns, buffer });
    }
}

Solution 2

First, if you're new to C# and multithreading and sockets, that is a lot to bite off for your first project. I recommend learning these individually.

That said, you may find Nito.Async.Sockets helpful; it includes an event-driven server socket and handles the multithreading concerns for you.

Solution 3

I would suggest to use WCF hosted as a windows service, which provide a scalable and multithread platform. It can be tailored as per protocol requirement as well. Here is an example which can be used as a reference:

http://msdn.microsoft.com/en-us/library/ms733069.aspx

Solution 4

I don't know about C# frameworks, but you can have a look at Twisted, an event driven Python framework. You can find examples of servers and clients code, similar to your needs.

Here is a sample of a very simple server that echoes back to client whatever it received from it:

#!/usr/bin/env python

# Copyright (c) 2001-2009 Twisted Matrix Laboratories.
# See LICENSE for details.

from twisted.internet.protocol import Protocol, Factory
from twisted.internet import reactor

### Protocol Implementation

# This is just about the simplest possible protocol
class Echo(Protocol):
    def dataReceived(self, data):
        """
        As soon as any data is received, write it back.
        """
        self.transport.write(data)


def main():
    f = Factory()
    f.protocol = Echo
    reactor.listenTCP(8000, f)
    reactor.run()

if __name__ == '__main__':
    main()

Regarding you last question:

P.S. Can I use just one port for all the clients?

Yes, you can (whatever language/framework you use).

Solution 5

Event driven doesn't exactly describe what you expect your system to work like because you describe polling your clients for data to process instead of your clients pushing their data to your service (triggering an event).

If you have very little idea about how to code a system like this you could look into existing solutions/products for your scenario.

I'd recommend checking out EAI tools like BlueIntegrator or BizTalk for integrating POS clients.

For your requirement concerning rolling out client updates you could look into BITS.

Share:
10,338
Ben
Author by

Ben

Updated on June 15, 2022

Comments

  • Ben
    Ben almost 2 years

    I'm working on an "application system" , where I also need to make a server application. I'm working in C# (.NET 4.0). The server will mainly collect data from different POS applications / clients (which should be around 50-100, but the server should be capable of handling also around 200-300 clients). From a single client a server will probably receive around 1KB about 100x times a day. The server mainly needs to accept the data, decrypt it and store it to disk. It should also check for changes in specific directory in order to send new configurations to clients, which shouldn't be very often.

    I'm quite new to C# and server programming so please bear with me. I thought about using threadpooling and async methods (there is a nice example using that in a book "C# in a nutshell"). But I spend quite some time looking for best solution and I found this. But multithreading brings more problems than benefits in my case. Thus I thought about even driven server. "A single process, handle every event (accepted connection, data available to read, can write to client, ...) on a callback." from " what is event driven web server". I find that the best solution to my problem.

    But I have no idea on how to code it, I couldn't find any examples about event driven servers. As far as I understand it I should make one thread (+ 1 for GUI), then create a TCP listener and then somehow create events so that when TCP listener could accept a client the event would fire and wake up the server, also when data to read from clients would be available it would wake up the server.

    Please help me out to code this, I'm totally lost. I know how I could do this using

    while(true)
    {
       check if client wants to connect
            accept client and add it to client list
       iterate through client list and check if anyone is sending data ...
            accept data and store it
       ...
      }
    

    But that is not event driven and is wasting CPU. Server will not be very active, so I'd like to make it as efficient as possible.

    Some examples would really help.

    Thank you for your time and answers.

    p.s. Can I use just one port for all the clients?

    EDIT: To clarify, I want to code an event driven server, but I don't know how to, thus I just made an example of what I know (client polling).