首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >TcpListener对SocketAsyncEventArgs

TcpListener对SocketAsyncEventArgs
EN

Stack Overflow用户
提问于 2015-01-03 13:23:16
回答 1查看 4.6K关注 0票数 5

是否有正当理由不使用TcpListener来实现高性能/高吞吐量的TCP服务器而不是SocketAsyncEventArgs

我已经使用SocketAsyncEventArgs实现了这个高性能/高吞吐量的TCP服务器,使用一个大的预分配的byte数组和用于接受和接收的SocketAsyncEventArgs池来处理那些固定缓冲区,使用一些低级别的东西和闪亮的智能代码与一些TPL数据流和一些Rx组合在一起,它的工作非常完美;在这方面,几乎教科书--实际上,我从其他代码中学到了80%以上的这些东西。

然而,也存在一些问题和关切:

  1. 复杂性:我不能将对此服务器的任何修改委托给团队的其他成员。这就限制了我处理这类任务,我也不能对其他项目的其他部分给予足够的关注。
  2. 内存使用(固定byte数组):使用SocketAsyncEventArgs,需要预先分配池。因此,对于处理100000个并发连接(更糟糕的情况,甚至在不同的端口上),大量的RAM是无用的;预先分配(即使在某些时候满足这些条件,服务器每天也应该能够处理1到2个这样的峰值)。
  3. TcpListener 实际上运行良好的:我实际上已经对TcpListener进行了测试(使用了一些技巧,比如在专用线程上使用AcceptTcpClient,而不是 async版本,然后将接受的连接发送到ConcurrentQueue,而不是创建Task的就地设置等),对于最新版本的.NET,它运行得非常好,几乎与SocketAsyncEventArgs一样好,没有数据丢失,内存脚打印也很低,这有助于避免服务器上浪费太多RAM,而且不需要预分配。

那么,为什么我没有看到TcpListener在任何地方被使用,而每个人(包括我自己)都在使用SocketAsyncEventArgs呢?我是不是遗漏了什么?

EN

回答 1

Stack Overflow用户

发布于 2015-01-03 13:57:46

我没有看到任何证据表明这个问题是关于TcpListener的。您似乎只关心处理已被接受的连接的代码。这种连接是独立于侦听器的。

SocketAsyncEventArgs是一个CPU负载优化.我相信你可以用它达到更高的运算速度。与正常的APM/TAP异步IO的区别有多大?肯定还不到一个数量级。可能在1.2倍到3倍之间。上次对环回TCP事务速率进行基准测试时,我发现内核占用了CPU使用量的大约一半。这意味着你的应用程序可以获得最多2倍的速度,通过无限优化。

请记住,SocketAsyncEventArgs是在2000年左右的时候添加到BCL中的,那时CPU的能力要差得多。

只有在有证据表明需要使用SocketAsyncEventArgs时才使用它。它会使你效率低得多。更有可能滋生臭虫。

下面是套接字处理循环所需的模板:

代码语言:javascript
复制
while (ConnectionEstablished()) {
 var someData = await ReadFromSocketAsync(socket);
 await ProcessDataAsync(someData);
}

非常简单的代码。由于await,没有回调。

如果您关心托管堆碎片:在启动时分配一个new byte[1024 * 1024]。当您希望从套接字读取时,请将单个字节读入此缓冲区的某个空闲部分。当单字节读取完成时,您将询问实际存在多少字节(Socket.Available),并同步提取其余的字节。这样,您只需插入一个相当小的缓冲区,仍然可以使用异步IO等待数据到达。

此技术不需要轮询。由于Socket.Available只能在没有从套接字读取的情况下增加,所以我们不会冒险执行太小的意外读取。

或者,您可以通过分配很少的大缓冲区和分发块来对抗托管堆碎片。

或者,如果你不认为这是一个问题,你不需要做任何事情。

票数 3
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/27755330

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档