概述
关于端口数量,大家都知道最多是65535
个端口。
这个来源于标识端口号的变量是16位
的,那么就是65536
个,去掉0
这个特殊端口,剩下65535
个,所以理论上最大可用数量是65535
。
但是实际中还有一些特殊端口已经定义好用处了,不能随便拿来给应用监听了,比如80,443
等端口号.
linux端口数量上限65535原因
这个原因很简单,上面概述中已经说过了。
但是linux
中打开一个端口是需要用一个文件描述符来标识,而且linux
还有端口范围。
net.ipv4.ip_local_port_range
是指本地端口范围,它的默认值是32768-61000
。
linux
的可用端口= 61000-32768=28232=大概2.8W个
文件描述符查询,默认的值是1024
,可以自己修改
ulimit -n
捞一张tcp
通信图,其中可以看到socket
是在tcp
上的抽象,把tcp
复杂的操作抽象为几个简单的接口来调用。
在socket
建立的时候客户端和服务端会各自打开一个网络套接字文件,linux
中会给这个文件分配一个文件描述符
linux服务端最大连接数量
上面说到linux
可用端口才2.8W
个,那是不是只能支持2.8W
个连接呢,那肯定不是的。
一个TCP连接的标记为一个四元组(source_ip, source_port, destination_ip, destination_port)
即(源IP,源端口,目的IP,目的端口)
四个元素的组合.
这样通过服务端的一个端口就可以和多个客户端建立多个连接了。
这里初步就可以知道,服务端的可以和客户端建立超过端口数量的连接数了。
进一步分析下服务端和客户端的连接建立过程
这个过程就直接捞大佬们的意见了
https://www.cnblogs.com/codingmengmeng/p/13676605.html
客户端:
socket()---->创建出 active_socket_fd (client_socket_fd)
bind()—>把active_socket_fd与ip,port绑定起来
connect()—>client_socket_fd 主动请求服务端的 listen_socket_fd
read()/write()---->读/写 socket io
close()---->关闭socket_fd
服务端:
socket()---->创建出 active_socket_fd
bind()—>把active_socket_fd与ip,port绑定起来
listen()---->active_socket_fd–> listen_socket_fd
等待客户端的client_socket_fd来请求连接accept()---->listen_socket_fd–>connec_socket_fd
把监听socket转变为连接socket,用于建立连接后的读写数据read()/write()---->读/写 socket io
close()---->关闭socket_fd
linux
内核中,socket
函数不管在客户端还是服务端,创建的套接字都是主动socket
,但是在服务端经过listen()
,后把其转变为listen_socket_fd(被动监听socket),经过accept()后转变为connect_socket_fd(已连接socket)
。
在转变为connect_socket_fd
之前,都是同一个socket
,只不过socket
的状态改变了,但是服务端经过accept()
后返回的socket
是新的socket
,用于连接后的read()/write()
。
一个tcp
连接的唯一标识是一个四元组<clientIP, clientPort, serverIP, serverPort>,serverIP和serverPort
是固定的,假定客户端也只有一个,即clientIP
也是固定的,则描述不同的tcp
连接就只剩下clientPort了
。而实际上每当客户端调用connect()
函数试图与服务端建立连接时,内核会为客户端分配一个临时端口作为源端口clientPort
,服务端通过accept()
函数感知到这个连接时,将返回一个全新的tcp
连接的描述字(connect_socket_fd)
。
所以,一个服务端端口是能建立多个连接的,因为每个连接中clientPort
都是不同的,在进行通信时,操作系统接收到向serverPort
发来的数据时,会在该端口产生的连接中查找到符合这个唯一标识并传递信息到对应的缓冲区。