假设我的Windows 7具有一个真实的网络接口和很少的环回接口。 我有启用IOCP的服务器,它接受来自客户端的连接。 我正在尝试尽可能多地模拟与服务器的真实客户端连接。
我的客户端代码只是建立了X个套接字连接 (请注意,客户端绑定到给定的接口):
const Int32 remotePort = 12345;
const Int32 MaxSockets = 60000;
Socket[] s = new Socket[MaxSockets];
IPEndPoint bindEndpoint = new IPEndPoint(IPAddress.Parse(args[0]), 0);
for (Int32 i = 0; i < MaxSockets; i++)
{
s[i] = new Socket(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp);
s[i].SetSocketOption(SocketOptionLevel.Socket, SocketOptionName.ReuseAddress, true);
s[i].Bind(bindEndpoint);
s[i].Connect(args[1], remotePort);
IPEndPoint socketInfo = (IPEndPoint)s[i].LocalEndPoint;
Console.WriteLine(String.Format("Connected socket {0} {1} : {2}", i, socketInfo.Address, socketInfo.Port));
}
在环回接口上,我有几个用于绑定的IP。 另外,我还使用真实的界面进行绑定。 当打开的套接字数量大约为每台机器64K时,我遇到了一个问题:
未处理的异常:System.Net.Sockets.SocketException:无法执行套接字上的操作,因为系统缺少足够的缓冲区空间或因为队列已满
我尝试了几个无助的事情: - 将MaxUserPort设置为最大值以及注册表中的其他一些建议的TCPIP设置。 - 尝试在不同的接口(真实接口和环回)上运行两个服务器并使用多个客户端。
它是Windows中的已知限制还是以某种方式克服它?
感谢您的帮助!
答案 0 :(得分:3)
我在某些Microsoft页面上发现:
... HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Tcpip\Parameters\MaxUserPort
registry子项定义为可以为通配符绑定分配端口的最大端口。MaxUserPort
注册表项的值定义动态端口范围...
因此,如果我强制端点使用某个端口,例如
IPEndPoint bindEndpoint = new IPEndPoint(IPAddress.Parse(args[0]), 54321);
然后我可以在系统中打开超过64K的同时套接字。
答案 1 :(得分:1)
在您的代码示例中,您正在调用Bind(bindEndpoint)
,但未显示bindEndpoint
的定义方式。检查:
环回地址不计算,因为许多系统专门用于路由和绑定目的。因此,绑定到环回中的端口可能会吸引所有地址上的端口,就像绑定到INADDR_ANY
(0.0.0.0
)一样。
答案 2 :(得分:0)
TCP和UDP都使用无符号的16位整数来指定端口号。我不认为任何操作系统中的任何实现最多能够为每个绑定地址打开超过65535个套接字。另外,如果Windows没有为每个适配器或每个绑定地址实现完全隔离的状态表,而是依赖于全局状态表,我不会感到惊讶。如果是这种情况,那将是Windows网络架构限制,而不是软的可配置限制。
答案 3 :(得分:0)
我已经开发了一种负载测试工具。
在Windows 10 / 16G RAM上运行,它可以成功与服务器建立60,000个连接。
但是当尝试创建更多连接时,该工具将很快报告“ socket WinError 10055没有可用的缓冲区空间”。
根据this article,我认为限制是整个操作系统的总套接字缓冲区大小,而不是打开的文件数。