【问题标题】:Creating 100,000 tcp connections using .NET使用 .NET 创建 100,000 个 tcp 连接
【发布时间】:2010-10-28 18:05:49
【问题描述】:

我正在用 C# 编写一个小的 Comet 服务器,为了测试它,我编写了一个小程序,它打开一堆连接,向每个连接写入一点文本,然后关闭每个连接:

int basePort = 30000;
IPAddress localAddress = new IPAddress( new byte[] { 127, 0, 0, 1 } );
List<Socket> sockets = new List<Socket>();

for( int i = 0; i < 20000; i++ ) {
    Socket s = new Socket( AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp );
    s.Bind( new IPEndPoint( localAddress, basePort + i ) );
    s.Connect( "localhost", 1999 );
    sockets.Add( s );
}

string message = "hello";
byte[] messageData = Encoding.ASCII.GetBytes( message );
foreach( Socket s in sockets ) {
    s.Send( messageData );
}

foreach( Socket s in sockets ) {
    s.Disconnect( false );
}

我目前使用的是 Windows XP,它只分配从 1025 到 5000 范围内的动态客户端端口,因此我添加了对从 30000 开始的端口的显式绑定。这使我的连接数从 4000 以下增加到 16000 多一点,但现在我在 Socket.Connect 上收到以下异常:

“无法对套接字执行操作,因为系统缺少足够的缓冲区空间或队列已满 127.0.0.1:1999”

有什么想法吗?更改发送和接收缓冲区大小似乎没有任何区别,而且似乎总是我的客户端应用程序坏了,而不是我的服务器。我意识到在达到 100,000 个连接之前我将用完客户端端口,但我仍然想更好地了解发生了什么。

【问题讨论】:

    标签: c# sockets comet


    【解决方案1】:

    我认为 100.000 个连接不是一个可行的目标。

    TCP/IP 端口是 16 位数字。所以任何高于 65535 的东西无论如何都是不行的。

    【讨论】:

    • 是的,在描述中我提到我将在达到 100,000 之前用完客户端端口,但我想在放弃之前尝试达到这样的硬性限制。跨度>
    • 我已经考虑了更多。 TCP/IP 端口实际上是通过 ip 和端口来寻址的,所以我可以为每个 ip 地址使用每个端口一次。连接到本地服务我可以使用本地地址 ( 127.0.0.1 ) 和默认的外部地址,这为我提供了超过 100,000 个不同的客户端端点。我已经对此进行了测试,它在我的 Windows XP 机器上运行良好。
    • 不过,如果您连接到某个外部或内部 ip/port,它仍然需要本地 ip/port 组合。例如假设我连接到 google.com:80 然后也分配了一个本地端口。这是您用完的本地端口组合。所以我不明白你怎么能超过 65536 的限制。
    【解决方案2】:

    您可能用完了非分页内存。每台机器和每进程的限制取决于安装的 RAM、操作系统、/3GB 开关设置等的数量。32 位操作系统 sku 对非分页内存的限制比 64 位操作系统 sku 低得多。

    【讨论】:

    • 这看起来很有希望,但是当我的测试客户端死机时,我使用的非分页内核内存不到 28MB。根据我的阅读,系统范围的限制应该至少为 100MB。看起来我也没有达到每个进程的限制,因为当客户端死掉时,它使用的内存少于 8MB,而服务器似乎在超过 10MB 时运行良好。
    【解决方案3】:

    Windows XP(可能还有其他版本)对任何时候允许的开放端口数量都有限制。这个MSDN article 可能有助于修改 TcpIp 参数以增加可用端口的数量并减少 Windows 在允许重用之前保持端口打开的时间。

    【讨论】:

    • 我想我已经处理了端口耗尽的问题。显式绑定用于处理有限数量的动态分配端口,并且 Socket.Disconnect 释放套接字的速度比 Socket.Close 快一点,因此我可以重新运行测试而无需等待 TIME_WAIT 间隔。跨度>
    • 我认为还有一个速率限制参数,但我没有找到 MSDN 参考。我的另一个怀疑是可用的网络缓冲区的数量。
    • 您不需要显式绑定来处理动态限制,您只需要按照 tvanfosson 的建议调整限制即可。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-09-20
    • 1970-01-01
    • 2012-11-11
    • 1970-01-01
    • 1970-01-01
    • 2011-07-15
    相关资源
    最近更新 更多