是否有正当理由不使用TcpListener
而不是TCP
来实现高性能/高吞吐量的SocketAsyncEventArgs
服务器?
我已经使用SocketAsyncEventArgs
实现了这种高性能/高吞吐量的TCP服务器,经历了各种各样的麻烦,使用一个预先分配的较大的byte
数组和SocketAsyncEventArgs
池来接收和接收那些固定的缓冲区,并使用一些低级的东西带有一些TPL数据流和一些Rx的 Shiny 智能代码,它可以完美运行;在这方面几乎是教科书-实际上,我已经从他人的代码中学到了80%以上的这些东西。
但是,存在一些问题和担忧:
团队成员。这使我无法完成此类任务,我可以
对其他项目的其他部分没有给予足够的重视。
byte
数组):使用SocketAsyncEventArgs
池需要被预先分配。因此,用于处理100000个并发连接
(更糟糕的情况,甚至在不同的端口上)一大堆RAM毫无用处地徘徊;
预先分配的(即使某些时候满足了这些条件,
服务器应该每天能够处理1或2个这样的高峰)。
TcpListener
实际上效果很好:我实际上已经对TcpListener
进行了测试(有一些技巧在专用线程上使用
AcceptTcpClient
,而不使用而不是 async
版本,然后将接受的连接发送到ConcurrentQueue
,而不是就地创建Task
等)并使用最新版本的.NET,效果很好,几乎一样好
作为
SocketAsyncEventArgs
,没有数据丢失并且内存占用少这有助于避免在服务器上浪费过多的RAM,并且不需要预先分配。
那么,为什么我看不到
TcpListener
在任何地方都被使用,并且每个人(包括我自己)都在使用SocketAsyncEventArgs
?我想念什么吗? 最佳答案
我看不到任何证据表明这个问题与TcpListener
有关。看来您只关心处理已被接受的连接的代码。这样的连接独立于监听器。SocketAsyncEventArgs
是CPU负载优化。我相信您可以通过它获得更高的每秒操作率。与普通APM/TAP异步IO的区别有多大?当然小于一个数量级。大概在1.2倍至3倍之间。上次我对环回TCP事务速率进行基准测试时,发现内核占用了大约一半的CPU使用率。这意味着通过无限优化,您的应用程序最多可以快2倍。
请记住,在2000年左右,即CPU的功能大大降低时,SocketAsyncEventArgs
已添加到BCL中。
仅在有证据证明需要时才使用SocketAsyncEventArgs
。它使您的工作效率大大降低。错误的可能性更大。
这是您的套接字处理循环应如下所示的模板:
while (ConnectionEstablished()) {
var someData = await ReadFromSocketAsync(socket);
await ProcessDataAsync(someData);
}
非常简单的代码。由于
await
,没有回调。如果您担心托管堆碎片:在启动时分配
new byte[1024 * 1024]
。当您想从套接字读取时,将一个字节读入此缓冲区的某些空闲部分。单字节读取完成后,您询问实际有多少字节(Socket.Available
),并同步提取其余字节。这样,您只需固定一个很小的缓冲区,仍然可以使用异步IO等待数据到达。此技术不需要轮询。由于
Socket.Available
只能在不从套接字读取的情况下才能增加,因此我们不会冒意外地读取太小的风险。另外,您可以通过分配一些非常大的缓冲区并分发块来对抗托管堆碎片。
或者,如果您不认为这是个问题,则无需执行任何操作。
关于c# - TcpListener与SocketAsyncEventArgs,我们在Stack Overflow上找到一个类似的问题:https://stackoverflow.com/questions/27755330/