当一个 TcpListener 接受所有连接时,总上传速度会变慢
本文关键字:速度 连接 一个 TcpListener | 更新日期: 2023-09-27 18:33:06
我最近在C# .NET Framework 4.0中遇到了一个奇怪的情况:
在一个简单的程序中,我创建了一个 TcpListener,指定其本地端口,启动它并使用异步接受函数来接收传入的连接请求。
一旦它有挂起的连接入站,服务器就会接受来自异步回调函数的 TcpClient 并将其记录到容器中(更具体地说,是 List<TcpClient>
(。
我编写了另一个简单的客户端程序,该程序一旦启动就连接到服务器,然后调用异步接收函数。
连接所有客户端后,服务器将使用 System.Threading.Tasks.Parallel.ForEach()
启动一组并行任务。
在每个任务中,我使用该列表中存储的 TcpClient 将数据发送到相应的客户端。 所有 TcpClient 同时发送数据(我检查了客户端,它们都在接收数据(。数据只是一个byte[8192]
,其中包含服务器程序启动时生成的随机数据。我让服务器重复发送它。
客户端的接收回调很简单。数据到达后,客户端只需忽略数据并运行另一个异步接收函数。
测试环境是 1Gbps LAN、一台服务器和多个客户端。
结果是:无论有多少客户端(从3~8个(连接到服务器,服务器的总上传速度永远不会超过13MByte/
秒。
然后我尝试了另一种方式:
我也在客户端创建了一个 TcpListener。客户端连接到服务器后,服务器也将连接到客户端的侦听端口。然后,服务器将此传出连接存储到列表中,而不是传入连接中。
这一次,测试结果变化很大:当 3 个客户端从服务器接收数据时,服务器的总上传速度接近 30MByte/s
;对于 5 个客户端,总上传速度上升到近 50MBytes/s
。
尽管此10MByte/s-per-client
限制可能是由于硬件或网络配置造成的,但它仍然比上述情况要好得多。
有人知道为什么吗?
我不知道这种行为的原因,但作为一种解决方法,我建议发送更大的缓冲区。比如 1MB(或至少 64k(。在 1Gbps LAN 上,如果您的应用发送更大的块(和更少的数据包(,则可能会更有效率。此外,启用巨型帧。
不要使用线程或任务进行处理。这会损害你的表现。
我制作了一个框架,它将帮助您开发高性能的网络应用程序,而不必关心实际的IO处理。
http://blog.gauffin.org/2012/05/griffin-networking-a-somewhat-performant-networking-library-for-net/