错误:Only one usage of each socket address (protocol/network address/port) is normally permitted.

 

版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/MBuger/article/details/83088894

说明

在windows中使用go实现了一个服务器压力测试工具,使用的TCP协议,在调试期间,出现问题如下

Only one usage of each socket address (protocol/network address/por
t) is normally permitted.
  • 1
  • 2

从字面上来看是告诉我们是socket被复用了。在网上查了原因之后发现是套接字用完了,也就是同时建立的TCP连接量超过了系统的限制。但是经过验证,发现其实并不是因为同时建立的TCP连接过多造成的。

问题分析

在我的测试工具中,我开启了20个协程去建立TCP连接,发送数据包,再关闭连接,并重复这个过程,也就是说同时也就最多建立20个TCP连接,远远小于windows中的tcp同时建立连接数的限制,并不可能出现TCP连接建立量超过系统限制的原因。那么又会是什么原因呢?
原来影响TCP连接建立数量的因素不止是最大建立连接数决定的。还有一系列的参数影响TCP连接的建立。在windows的注册表中的HKEY_LOCAL_MACHINE \System \CurrentControlSet \services \Tcpip \Parameters中,
在这里插入图片描述

最大TCB 数量

系统为每个TCP 连接分配一个TCP 控制块(TCP control block or TCB),这个控制块用于缓存TCP连接的一些参数(源端口、目的端口、目的ip、序号、应答序号、对方窗口大小、己方窗口大小、tcp状态、tcp输入/输出队列、应用层输出队列、tcp的重传有关变量等),每个TCB需要分配 0.5 KB的pagepool 和 0.5KB 的Non-pagepool,也就说,每个TCP连接会占用 1KB 的系统内存。

系统的最大TCB数量由如下注册表设置决定
[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
MaxFreeTcbs = 2000 (Default = RAM dependent, but usual Pro = 1000, Srv=2000)
这里也就表示最大可同时创建两千个TCP连接。
但是通过调整注册表中的以下参数可以改变这个值。

MaxUserPort = 65534 (Decimal) 
MaxHashTableSize = 65536 (Decimal) 
MaxFreeTcbs = 16000 (Decimal) 
  • 1
  • 2
  • 3

把这几项都调到最大。即可把TCP同时建立数扩大到16000。此时确实发现,这个报错会出现在当tcp连接建立到16000左右的时候。但是依然不是同时建立这么多连接,每次建立完都有关闭tcp。

猜想

tcb控制块并不是断开TCP连接后直接释放,而是要等待TCP连接time_wait时间之后再释放。

验证

重启服务器,再次使用测试工具进行测试。
在这里插入图片描述

如图所示,当短时间内建立TCP连接数到16000左右的时候再次出现问题。
关闭测试工具,等待1分钟后,启动测试工具。依然报错。
关闭测试工具,在等待1分钟,也就是过了TCP默认的time_wait时间,再启动测试工具,不再报错又可以重新建立连接。
验证tcb控制块并不是断开TCP连接后直接释放,而是要等待TCP连接time_wait时间之后再释放。

 

注册表操作

win+R 输入regedit ,找到相关位置,右键新建参数

Socket 编程时,单机最多可以建立多少个 TCP 连接,受到操作系统的影响。

  Windows 下单机的TCP连接数受多个参数影响:

   最大TCP连接数

[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
TcpNumConnections = 0x00fffffe (Default = 16,777,214)

    以上注册表信息配置单机的最大允许的TCP连接数,默认为 16M。这个数值看似很大,这个并不是限制最大连接数的唯一条件,还有其他条件会限制到TCP 连接的最大连接数。

最大动态端口数

TCP客户端和服务器连接时,客户端必须分配一个动态端口,默认情况下这个动态端口的分配范围为 1024-5000 ,也就是说默认情况下,客户端最多可以同时发起3977 个Socket 连接。我们可以修改如下注册表来调整这个动态端口的范围

[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
MaxUserPort = 5000 (Default = 5000, Max = 65534)

最大TCB 数量

系统为每个TCP 连接分配一个TCP 控制块(TCP control block or TCB),这个控制块用于缓存TCP连接的一些参数,每个TCB需要分配 0.5 KB的pagepool 和 0.5KB 的Non-pagepool,也就说,每个TCP连接会占用 1KB 的系统内存。

系统的最大TCB数量由如下注册表设置决定

[HKEY_LOCAL_MACHINE \System \CurrentControlSet \Services \Tcpip \Parameters]
MaxFreeTcbs = 2000 (Default = RAM dependent, but usual Pro = 1000, Srv=2000)

非Server版本,MaxFreeTcbs 的默认值为1000 (64M 以上物理内存)

Server 版本,这个的默认值为 2000。

也就是说,默认情况下,Server 版本最多同时可以建立并保持2000个TCP 连接。

最大TCB Hash table 数量

TCB 是通过Hash table 来管理的,下面注册表设置决定了这个Hash table 的大小

HKEY_LOCAL_MACHINE \System \CurrentControlSet \services \Tcpip \Parameters]
MaxHashTableSize = 512 (Default = 512, Range = 64-65536)

这个值指明分配 pagepool 内存的数量,也就是说,如果MaxFreeTcbs = 1000 , 则 pagepool 的内存数量为 500KB

那么 MaxHashTableSize 应大于 500 才行。这个数量越大,则Hash table 的冗余度就越高,每次分配和查找 TCP  连接用时就越少。这个值必须是2的幂,且最大为65536.

参考: IBM WebSphere Voice Server 在windows server 2003 下的典型配置

      MaxUserPort = 65534 (Decimal)

      MaxHashTableSize = 65536 (Decimal)

      MaxFreeTcbs = 16000 (Decimal)

这里我们可以看到 MaxHashTableSize 被配置为比MaxFreeTcbs 大4倍,这样可以大大增加TCP建立的速度。

 

 

Logo

旨在为数千万中国开发者提供一个无缝且高效的云端环境,以支持学习、使用和贡献开源项目。

更多推荐