socket端口数量限制问题
linux socket使用16bit无符号整型表示端口号,最大到65535。关于端口号,有一个经典的误解就是,因为端口号有限,所以一个客户端最多建立65536个socket连接,但实际上并不是这么回事,端口是可以复用的。
一个socket连接是一个[srcip, srcport, destip, destport]组成的四元组,如果再算上协议(tcp、udp、rawsocket等)就是五元组了,这个四元组中,只要有一个元素不同,就能区分两个连接;我们平时所遇到端口不够用的问题,大多出现在压测环境中,用客户端不断向某一个服务器建立连接发请求,当连接超过一定数量后,connect会出错提示Cannot assign requested address。对于这样的场景,四元组的destip,destport是确定的,对于单网卡机器srcip也是确定的(不考虑虚拟网卡情况),可变的就只有srcport,而端口的取值只能在0-65535,再加上系统的一些保留端口是不可用的,所以客户端到该特定服务间的连接数就受端口数目的限制,当连接到其他服务器时,本地的端口是可以复用的。实际上,在 不指定端口的情况下连接服务器,可用的端口号在/proc/sys/net/ipv4/ip_local_port_range中配置,默认为32768-61000。
为了验证源端口复用,作如下小实验,首先为了避免OS资源消耗过大,将local port range设置为60001 61000,即只提供1000个可用端口号;写个连接服务器的小程序,分别向两个不同的服务各建立900个连接,总连接数1800超过可用端口1000;执行连接程序后,通过netstat发现,1800个连接全部建立成功,通过下面的输出信息可以发现,源端口是可以复用的,端口号数量限制问题实际上是不存在的。
- tcp 0 0 x.x.36.208:60513 x.x.36.204:3200 ESTABLISHED off (0.00/0/0)
- tcp 0 0 x.x.36.208:60513 x.x.36.203:3200 ESTABLISHED off (0.00/0/0)