Search code examples
c#multithreadingasynchronousclient-servertcpclient

C# best way to implement TCP Client Server Application


I want to extend my experience with the .NET framework and want to build a client/server application. Actually, the client/server is a small Point Of Sale system but first, I want to focus on the communication between server and client. In the future, I want to make it a WPF application but for now, I simply started with a console application.

2 functionalities:

  • client(s) receive(s) a dataset and every 15/30min an update with changed prices/new products
    (So the code will be in a Async method with a Thread.sleep for 15/30 mins).

  • when closing the client application, sending a kind of a report (for example, an xml)

On the internet, I found lots of examples but i can't decide which one is the best/safest/performanced manner of working so i need some advice for which techniques i should implement.

CLIENT/SERVER

I want 1 server application that handles max 6 clients. I read that threads use a lot of mb and maybe a better way will be tasks with async/await functionallity.

Example with ASYNC/AWAIT

http://bsmadhu.wordpress.com/2012/09/29/simplify-asynchronous-programming-with-c-5-asyncawait/

Example with THREADS

mikeadev.net/2012/07/multi-threaded-tcp-server-in-csharp/

Example with SOCKETS

codereview.stackexchange.com/questions/5306/tcp-socket-server

This seems to be a great example of sockets, however, the revisioned code isn't working completely because not all the classes are included msdn.microsoft.com/en-us/library/fx6588te(v=vs.110).aspx This example of MSDN has a lot more with Buffersize and a signal for the end of a message. I don't know if this just an "old way" to do this because in my previous examples, they just send a string from the client to the server and that's it.

.NET FRAMEWORK REMOTING/ WCF I found also something about the remoting part of .NET and WCF but don' know if I need to implement this because i think the example with Async/Await isn't bad.

SERIALIZED OBJECTS / DATASET / XML

What is the best way to send data between it? Juse an XML serializer or just binary?

Example with Dataset -> XML

stackoverflow.com/questions/8384014/convert-dataset-to-xml

Example with Remoting

akadia.com/services/dotnet_dataset_remoting.html

If I should use the Async/Await method, is it right to something like this in the serverapplication:

        while(true)
        {
            string input = Console.ReadLine();
            if(input == "products")
                SendProductToClients(port);
            if(input == "rapport")
            {
                string Example = Console.ReadLine();
            }                                
        }

Solution

  • Threads are not terribly expensive, considering the amount of RAM available on modern systems, so I don't think it's helpful to optimize for a low thread count. Especially if we're talking about a difference between 1 thread and 2-5 threads. (With hundreds or thousands of threads, the cost of a thread starts to matter.)

    But you do want to optimize for minimal blocking of whatever threads you do have. So for example instead of using Thread.Sleep to do work on 15 minute intervals, just set a timer, let the thread return, and trust the system to invoke your code 15 minutes later. And instead of blocking operations for reading or writing information over the network, use non-blocking operations.

    The async/await pattern is the new hotness for asynchronous programming on .Net, and it is a big improvement over the Begin/End pattern that dates back to .Net 1.0. Code written with async/await is still using threads, it is just using features of C# and .Net to hide a lot of the complexity of threads from you - and for the most part, it hides the stuff that should be hidden, so that you can focus your attention on your application's features rather than the details of multi-threaded programming.

    So my advice is to use the async/await approach for all of your IO (network and disk) and use timers for periodic chores like sending those updates you mentioned.

    And about serialization...

    One of the biggest advantages of XML over binary formats is that you can save your XML transmissions to disk and open them up using readily-available tools to confirm that the payload really contains the data that you thought would be in there. So I tend to avoid binary formats unless bandwidth is scarce - and even then, it's useful to develop most of the app using a text-friendly format like XML, and then switch to binary after the basic mechanism of sending and receiving data have been fleshed out.

    So my vote is for XML.

    And regarding your code example, well ther's no async/await in it...

    But first, note that a typical simple TCP server will have a small loop that listens for incoming connections and starts a thread to hanadle each new connection. The code for the connection thread will then listen for incoming data, process it, and send an appropriate response. So the listen-for-new-connections code and the handle-a-single-connection code are completely separate.

    So anyway, the connection thread code might look similar to what you wrote, but instead of just calling ReadLine you'd do something like "string line = await ReadLine();" The await keyword is approximately where your code lets one thread exit (after invoking ReadLine) and then resumes on another thread (when the result of ReadLine is available). Except that awaitable methods should have a name that ends with Async, for example ReadLineAsync. Reading a line of text from the network is not a bad idea, but you'll have to write ReadLineAsync yourself, building upon the existing network API.

    I hope this helps.