2

Okay, I read many questions involving writing high scale-able servers but I never really came across a good answer. Anyway I want to create a high scale-able clients, which handles lots of data and connections. What I created was a simple client using SocketAsyncEventArgs and C#5 async/await like this:

public async Task<int> SendAsync(byte[] buffer, int offset, int size)
{
    var socketArgs = new SocketAsyncEventArgs();
    var tcs = new TaskCompletionSource<int>();

    socketArgs.SetBuffer(buffer, offset, size);
    socketArgs.Completed += (sender, args) =>
    {
        tcs.SetResult(socketArgs.BytesTransferred);
        LastSocketError = socketArgs.SocketError;
    };

    if (_clientSocket.SendAsync(socketArgs)) 
        return await tcs.Task;

    LastSocketError = socketArgs.SocketError;
    return socketArgs.BytesTransferred;
}

And that for ConnectAsync, ReceiveAsync and AcceptAcync. This works great for the client part, but on my server I don't know how to get it right.. (I would end up creating a Thread for every Client for receiving.) I can use the APM (Begin/End) or using EventHandler but that kills the purpose of using async/await and in the end it isn't memory efficient when creating a new SocketAsyncEventArgs for every call. I tried creating a Pool (using a ConcurrentBag) but then I still had to create a TaskCompletionSource over and over (as you can use it only once.)

So I don't think this is a good idea of creating this, although I really like it.. What would be a good design to create a high scale-able and high performance server?

pindumb
  • 135
  • 4
joell
  • 396
  • 6
  • 17
  • 1
    This wasn't informative enough? http://stackoverflow.com/questions/869744/how-to-write-a-scalable-tcp-ip-based-server/895249#895249 – DavidN Feb 16 '14 at 14:27
  • 4
    You use terms like "lots of data and connections" and "isn't memory efficient". Have you done performance testing on an existing solution, or are you just assuming that the standard approach to asynchronous I/O is insufficient? – Stephen Cleary Feb 16 '14 at 14:35
  • @DavidN I guess I missed that answer.. – joell Feb 16 '14 at 14:41
  • @StephenCleary I'm assuming that when I have lots of clients connected and the server handles lots of data it isn't memory efficient when you create a SocketAsyncEventArgs for every call and create a new thread/task for every client to listen for receiving data? – joell Feb 16 '14 at 14:43
  • 2
    @iVision: The point is that "lots" and "memory efficient" are very relative terms. `SocketAsyncEventArgs` is a very specialized API that you probably (>99.9%) don't need. It's much easier to wrap the `*Begin`/`*End` into tasks using `TaskFactory.FromAsync`. – Stephen Cleary Feb 16 '14 at 15:03
  • @iVision, you probably shouldn't be worrying about threading at all, if you use async wrappers like `TaskFactory.FromAsync` as suggested by @StephenCleary. Simply continue on the I/O completion pool thread the socket operation happened to complete on. Check this: http://stackoverflow.com/q/21013751/1768303 – noseratio Feb 16 '14 at 21:12

1 Answers1

1

We could, of course, adjust such asynchronous methods with the task, but that would largely defeat the purpose of these methods, similar to the assignment of an IAsyncResult in the case of APM. However, even so, we want to be able to take advantage of the async / await support of the compiler to facilitate the writing of asynchronous code using sockets. We want our cake and eat it too. Of course, the compiler admits expecting more than Tasks. So, if you have a specialized scenario like this, you can take advantage of the support based on compiler patterns to wait for things. More information: https://blogs.msdn.microsoft.com/pfxteam/2011/12/15/awaiting-socket-operations/

Jljf
  • 11
  • 1