Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

What is the current standard of practice to implement an async socket client?

I look for the best practices to meet the following requirements:

  • A framework that handles several client sockets in an asynchronous fashion
  • Each incoming message protocol dictates that each message is of format string and is marked complete with a line feed character '\n'.
  • I have full control of the client side but not server side. Server accepts and sends string based messages with line feed character to mark completion of the message.
  • I want to be able to send messages through each connected socket at any given time (each socket can receive and send messages).
  • Incoming messages should be forwarded through a callback.
  • I want to be able to chose in my implementation whether all incoming complete messages from all connected sockets are routed to one single callback or whether each socket client implements its own callback.
  • I connect at a maximum 4 clients/sockets. So I look for suggestions that capitalize on such limited amounts of sockets, however, are capable of managing all those concurrently.

I wonder whether the framework where I use BeginReceive and EndReceive with implemented IAsyncResult callback is state of the art given I target .Net 4.5. Is there a better solution, such as using NetworkStream or other API choices? What really bugs me with the BeginReceive/EndReceive implementation is that after EndReceive I have to call BeginReceive again and register the callback again. That sounds like an awful amount of overhead to me. Why can't new data be added async at any time and at the same time another context builds complete messages that are then routed through a raised event?

The argument of using IAsyncResult is often given in that thread handling is taken care of, but what speaks against the following: Using a NetworkStream and simply read from and write to the stream. As mentioned only string messages are exchanged and each message per protocol is marked complete by the line feed character. A separate task/thread would poll a streamreader (based on the networkstream) through ReadLine(). It probably can`t get simpler than that, can it?

What I am basically asking is, how can the following code be made truly async?

public class SocketClient
{
    private TcpClient client;
    private StreamReader reader;
    private StreamWriter writer;

    public event Action<string> MessageCallback;

    public SocketClient(string hostname, int port)
    {
        client = new TcpClient(hostname, port);

        try
        {
            Stream stream = client.GetStream();
            reader = new StreamReader(stream);
            writer = new StreamWriter(stream);
            writer.AutoFlush = true;

            //Start Listener on port
            StartListener();
        }
        catch (Exception e)
        {
            throw new Exception(e.ToString());
        }
    }

    public void StartListener()
    {
        Task task = Task.Factory.StartNew(() =>
            {
                while (true)
                {
                    if (MessageCallback != null)
                    {
                        MessageCallback(reader.ReadLine());

                    }

                    //Thread.Sleep(200);
                }
            });
    }

}
like image 920
Matt Avatar asked Feb 24 '13 07:02

Matt


2 Answers

There is no current standard or common practice at the moment. You have a number of choices, each with advantages and disadvantages:

  1. Wrap the TAP methods into Tasks and use async/await.
    • Advantages: Pretty straightforward to do.
    • Disadvantages: It's low-level; you have to manage all the various async operations yourself within an "infinite" loop as well as handle state management for each connection.
  2. Wrap the Socket *Async methods into Tasks and use async/await.
    • Advantages: Speed. This is the fastest and most scalable option.
    • Disadvantages: You still have low-level "infinite" loops and state management, where the code is more complex than option (1).
  3. Convert socket completions to Rx events.
    • Advantages: You can encapsulate the "infinite" loops and treat the completions as a stream of events.
    • Disadvantages: There's a hefty learning curve to Rx, and this is not a simple use case. Managing the state of each connection can get complex.
  4. Convert socket completions to TPL Dataflow.
    • Advantages: (same as Rx): encapsulating the loops and getting a stream of data.
    • Disadvantages: The learning curve is easier than Rx, but you still have some complex state management for each connection.
  5. Use an existing library such as my Nito.Async library, which provides EAP socket classes.
    • Advantages: Very easy to use; everything is an event and there's no multithreading concerns. Also, the tricker parts of state management are done for you.
    • Disadvantages: Doesn't scale as well as the lower-level solutions.

For your situation (a few hundred messages per second on less than a hundred sockets), I would recommend using my Nito.Async library. It's the easiest one of these options to get working.

Regarding your protocol, you'll have to parse out the \ns by hand and do your own buffering. (That's true for all the choices above).

like image 97
Stephen Cleary Avatar answered Oct 12 '22 12:10

Stephen Cleary


As per my recommendation please use new Async form of XXXReceive and 'XXXSend' (where XXX stands for Begin and End), the new methods available are ReceiveAsync and SendAsync methods which uses SocketAsyncEventArgs to pass the socket and other information on the callbacks event handlers.

I had seen a good working example of socket client and server on msdn archive which was scalable upto 500 connections (As I had tested in one of project adaptation from it) but currently I am not able to find that link from googling.. but here is another link from msdn archive on the same topic hopefully it will help you - Get Closer to the Wire with High-Performance Sockets in .NET..

UPDATE

First of all I can only provide you idea to final implementation and if possible some short example code snippets. ok here I go with more details

I think you can jump to last paragraph's link. ;)

Let me highlight once because I want to, I said SendAsync and ReceiveAsync not BeginReceive/EndReceive and BeginSend/EndSend i.e. Event-based Async Pattern (EAP)

Benefit of using Async form of Socket methods is that they are exception-less approach to socket programming which can prove faster than BeginSend/EndSend methods.

Here is the link for the sample which I have found to be useful upto 500 PARALLEL connections - Networking Samples for .NET v4.0

For you need to use await/async feature of .NET 4.5. Here is the .NET 4.5 code snippet showing usage of WebSocket class which of can be adapted to Socket implementations also - Support for WebSockets Protocol (I guess WebSocket's AspNetWebSocketContext will be Socket's SocketAsyncEventArgs)

I found Awaiting Socket Operations sample code from MSDN - Parallel Programming team blog which can be useful to use to implement await/async from .NET 4.5 framework.

I hope this proves helpful to you.

like image 44
Harsh Baid Avatar answered Oct 12 '22 10:10

Harsh Baid