2

好的,我阅读了许多涉及编写高可扩展服务器的问题,但我从未真正找到一个好的答案。无论如何,我想创建一个高度可扩展的客户端,它可以处理大量数据和连接。我创建的是一个使用 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 时内存效率不高。我尝试创建一个池(使用 ConcurrentBag),但我仍然不得不一遍又一遍地创建一个 TaskCompletionSource(因为你只能使用它一次。)

所以我不认为创建这个是一个好主意,尽管我真的很喜欢它。创建一个高扩展性和高性能服务器的好设计是什么?

4

1 回答 1

1

当然,我们可以根据任务调整此类异步方法,但这在很大程度上会破坏这些方法的目的,类似于在 APM 的情况下分配 IAsyncResult。然而,即便如此,我们希望能够利用编译器的 async/await 支持来促进使用套接字编写异步代码。我们想要我们的蛋糕并且也吃掉它。当然,编译器承认期望的不仅仅是任务。因此,如果您有这样的专门场景,您可以利用基于编译器模式的支持来等待事情。更多信息: https ://blogs.msdn.microsoft.com/pfxteam/2011/12/15/awaiting-socket-operations/

于 2018-09-19T05:02:00.297 回答