What is the current standard of practice to implement an async socket client?
asynchronous, c#, networkstream, sockets, tcp
Solution
There is no current standard or common practice at the moment. You have a number of choices, each with advantages and disadvantages:
- Wrap the TAP methods into `Task`s 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.
- Wrap the Socket `*Async` methods into `Task`s 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).
- 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.
- 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.
- 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 `\n`s by hand and do your own buffering. (That's true for all the choices above).
Problem
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); } }); } } ```