使用SocketAsyncEventArgs编写高可伸缩套接字服务器

时间:2014-02-16 14:18:39

标签: c# sockets asynchronous task-parallel-library socketasynceventargs

好的,我读了许多涉及编写高规模服务器的问题,但我从来没有真正得到过一个好的答案。无论如何,我想创建一个高规模的客户端,处理大量的数据和连接。我创建的是一个使用SocketAsyncEventArgs和C#5 async / await的简单客户端,如下所示:

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;
}

适用于ConnectAsync,ReceiveAsync和AcceptAcync。这适用于客户端部分,但在我的服务器上我不知道如何正确...(我最终会为每个客户端创建一个线程来接收。)  我可以使用APM(开始/结束)或使用EventHandler但是这会杀死使用async / await的目的,并且最终在为每个调用创建新的SocketAsyncEventArgs时它不具有内存效率。我尝试创建一个Pool(使用ConcurrentBag),但后来我仍然不得不一遍又一遍地创建一个TaskCompletionSource(因为你只能使用它一次。)

所以我认为这不是创造这个的好主意,虽然我真的很喜欢..创建高规模和高性能服务器的好设计是什么?

1 个答案:

答案 0 :(得分:0)

我们当然可以根据任务调整此类异步方法,但这将大大削弱这些方法的目的,类似于在APM中分配IAsyncResult的目的。但是,即使如此,我们仍希望能够利用编译器的async / await支持来促进使用套接字编写异步代码。我们要我们的蛋糕,也吃。 当然,编译器承认期望比Tasks要大。因此,如果您有类似这样的特殊情况,则可以利用基于编译器模式的支持来等待事情。 更多信息: https://blogs.msdn.microsoft.com/pfxteam/2011/12/15/awaiting-socket-operations/