Async / await or Begin / End with TcpListener?

I started creating a tcp server that can receive many clients and simultaneously receive new data from all clients.

So far, I have used IOCP for tcp servers, which were quite lightweight and convenient, but this time I want to use Async / Await technology. which was released in C # 5.0.

The problem is that when I started writing the server using async / await, I realized that when using the tcp server for several async / await tech users. and conventional synchronization methods will work the same.

Here is a simple example:

class Server { private TcpListener _tcpListener; private List<TcpClient> _clients; private bool IsStarted; public Server(int port) { _tcpListener = new TcpListener(new IPEndPoint(IPAddress.Any, port)); _clients = new List<TcpClient>(); IsStarted = false; } public void Start() { IsStarted = true; _tcpListener.Start(); Task.Run(() => StartAcceptClientsAsync()); } public void Stop() { IsStarted = false; _tcpListener.Stop(); } private async Task StartAcceptClientsAsync() { while (IsStarted) { // ******** Note 1 ******** var acceptedClient = await _tcpListener.AcceptTcpClientAsync(); _clients.Add(acceptedClient); IPEndPoint ipEndPoint = (IPEndPoint) acceptedClient.Client.RemoteEndPoint; Console.WriteLine("Accepted new client! IP: {0} Port: {1}", ipEndPoint.Address, ipEndPoint.Port); Task.Run(() => StartReadingDataFromClient(acceptedClient)); } } private async void StartReadingDataFromClient(TcpClient acceptedClient) { try { IPEndPoint ipEndPoint = (IPEndPoint) acceptedClient.Client.RemoteEndPoint; while (true) { MemoryStream bufferStream = new MemoryStream(); // ******** Note 2 ******** byte[] buffer = new byte[1024]; int packetSize = await acceptedClient.GetStream().ReadAsync(buffer, 0, buffer.Length); if (packetSize == 0) { break; } Console.WriteLine("Accepted new message from: IP: {0} Port: {1}\nMessage: {2}", ipEndPoint.Address, ipEndPoint.Port, Encoding.Default.GetString(buffer)); } } catch (Exception) { } finally { acceptedClient.Close(); _clients.Remove(acceptedClient); } } } 

Now, if you see the lines under "Note 1" and "Note 2", it can easily be changed to:

Note 1 of

 var acceptedClient = await _tcpListener.AcceptTcpClientAsync(); 

to

 var acceptedClient = _tcpListener.AcceptTcpClient(); 

And note 2 of

 int packetSize = await acceptedClient.GetStream().ReadAsync(buffer, 0, 1024); 

to

 int packetSize = acceptedClient.GetStream().Read(buffer, 0, 1024); 

And the server will work exactly the same.

So why use async / await in a tcp listener for multiple users if it is the same as using regular synchronization methods?

Should I continue to use IOCP in this case? , because for me it is quite easy and convenient, but I'm afraid that it will become obsolete or even no longer available in new versions of .NET.

+6
source share
3 answers

So far, I have used IOCP for tcp servers, which were quite lightweight and convenient, but this time I want to use Async / Await technology. which was released in C # 5.0.

I think you need to get your terminology right.

Having the BeginOperation and EndOperation , the asynchronous programming model (APM) is called. Having one method to return a Task (or Task<T> ) is called a Task<T> Based Asynchronous Template (TAP). I / O Ports (IOCPs) are a way to handle asynchronous operations on Windows and asynchronous I / O methods using both APM and TAP.

This means that the performance of APM and TAP will be very similar. The big difference between the two is that the code using TAP and async - await much more readable than the code using APM and callbacks.

So, if you want (or should) write your code asynchronously, use TAP and async - await if you can. But if you have no reason for this, just write your code synchronously.

On the server, scalability is a good reason for using asynchrony: asynchronous code can process many more requests at the same time, since it tends to use fewer threads. If you do not need scalability (for example, because you will not have many users at the same time), then asynchrony does not make much sense.


In addition, your code contains some methods that should be avoided:

  • Do not use async void methods, there is no good way to tell when they will finish, and they have poor exception handling. The exception is event handlers, but this mainly applies to GUI applications.
  • Do not use Task.Run() if you do not need it. Task.Run() can be useful if you want to leave the current thread (usually a user interface thread) or if you want to execute synchronous code in parallel. But it makes no sense to use it to run asynchronous operations in server applications.
  • Do not ignore the returned Task methods if you are not sure that they are not going to throw an exception. Exceptions from an ignored Task do nothing, which can very easily hide an error.
+17
source

After a couple of searches, I found this

Q This is a list of TCPServer methods, but which one is best for managing 5000+ clients in a few seconds?

A : my assumption " Writing asynchronous methods " is greater if you are working with the database at the same time. Asynchronous methods and iterators will do more

+1
source

here is sample code using async / await.

async is waiting for tcp server

I think it is easier to build a tcp server using async / wait than iocp.

0
source

Source: https://habr.com/ru/post/955267/


All Articles