首先,题中所说的65535个连接是指客户端连接数的限制。在tcp应用中,服务端预先监听固定端口,客户端主动发起连接,三次握手后建立tcp连接。那么对于单机来说,最大并发tcp连接数是多少呢?如何识别TCP连接在确定最大连接数之前,我们先来看看系统是如何识别一个tcp连接的。系统使用一个四元组来唯一标识一个TCP连接:{localip,localport,remoteip,remoteport}={localip,localport,remoteip,remoteport}client最大tcp连接数client每次发起一个tcp连接请求time,除非端口被绑定,通常让系统选择一个空闲的本地端口(localport),这个端口是独占的,不能与其他tcp连接共享。tcp端口的数据类型是unsignedshort,所以本地端口数最多只有65536个,0号端口有特殊意义,不能使用。这样,最大可用端口数只有65535个,所以当全部作为client时,一个client的tcp连接数最大为65535个,这些连接可以连接到不同的serverips。服务器上的最大tcp连接数服务器通常监听本地某个端口,等待客户端的连接请求。不考虑地址复用(Unix的SO_REUSEADDR选项),即使server端有多个IP,本地监听端口是独占的,所以server端只有remoteip(即clientip)和remoteport(clientip)-侧tcp连接4元组。terminalport)是可变的,所以最大tcp连接数是客户端ip数×客户端端口数。对于IPV4,不考虑ip地址分类等因素,最大tcp连接数约为2的32次方(ip数)×2的16次方(端口数),即最大tcp连接数服务器端单机的连接数约为2的48次方。上面的实际tcp连接数是单机理论最大连接数。在实际环境中,受限于机器资源和操作系统,尤其是服务器端,最大并发tcp连接数与理论上限相差甚远。unix/linux下限制连接数的主要因素是内存和允许的文件描述符数(每个tcp连接占用一定的内存,每个socket是一个文件描述符),1024以下的端口通常是保留的港口。因此,在服务器端,通过增加内存,修改最大文件描述符数等参数,单机最大并发TCP连接数超过10万,甚至上百万是没有问题的。这显然是思维的误区。65535指的是可用端口总数,并不是说服务器同时只能接受65535个并发连接。比如:我们做了一个网站,绑定了TCP的80端口,这样一来,所有访问这个网站的用户都是通过服务器的80端口访问的,而不是其他端口。可见端口是可以复用的。即使Linux服务器只监听80端口的服务,也允许10万、100万用户连接到服务器。Linux系统不限制连接数。至于服务器能否承受这么多连接数,取决于服务器的硬件配置、软件架构和优化。01我们知道,两个进程进行通信最基本的前提是能够唯一标识一个进程。在本地进程通信中,我们可以使用PID来唯一标识一个进程,但是PID只是本地唯一的,网络中两个进程之间PID冲突的概率很大。这时候就需要另辟蹊径了。IP地址可以唯一标识主机,TCP层协议和端口号可以唯一标识主机的一个进程。这样IP地址+协议+端口号就可以在网络中唯一标识一个进程。在能够唯一标识网络中的进程后,它们就可以使用套接字进行通信了。套接字(socket)是介于应用层和传输层之间的一个抽象层。它将TCP/IP层的复杂操作抽象成几个简单的接口供应用层调用,实现网络中的进程通信。Socket起源于Unix,是“打开-读取/写入-关闭”模式的一种实现。服务器和客户端各维护一个“文件”。连接建立并打开后,他们可以将内容写入自己的文件供对方读取或读取对方的内容,并在通信结束时关闭文件。02唯一能确定一个连接的就是4个东西:服务器的IP,服务器的端口,客户端的IP,客户端的端口,服务器的IP和端口可以不变,只要客户端的IP和端口各不相同其他,可以确定多个连接。一个socket可以建立多个连接,一个TCP连接被标记为四元组(source_ip,source_port,destination_ip,destination_port),即四个元素(源IP,源端口,目的IP,目的端口)的组合。只要四种元素组合中的一种元素不同,就可以区分出不同的联系。例如:你的主机IP地址是1.1.1.1,监听8080端口,当从2.2.2.2发出连接请求时,端口是5555。这个连接的四元数是(1.1.1.1,8080,2.2.2.2,5555)。此时2.2.2.2发送第二次连接请求,端口为6666,新连接的四元数为(1.1.1.1,8080,2.2.2.2,6666),则两个连接已经建立在8080端口你的主人;(2.2.2.2)发送的第三个连接请求的端口为5555(或6666)。第三个连接的请求无法建立,因为没有办法和上面两个连接区分开来。同样,一个TCP套接字和一个UDP套接字可以绑定相同的端口号和IP地址,因为虽然端口号相同,但由于协议不同,端口号是完全独立的。TCP/UDP一般使用五元组来定位一个连接:source_ip,source_port,destination_ip,destination_port,protocol_type(源IP,源端口,目的IP,目的端口,协议号)综上所述,服务器的并发数不是由65535决定的TCP的端口。服务器同时能承受的并发数由带宽、硬件、程序设计等多种因素决定。所以你也能理解为什么淘宝、腾讯、今日头条、百度、新浪、哔哔哔等等能承受每秒上亿的并发访问,就是因为他们使用了服务器集群。服务器集群分布在全国各地的大型机房。流量小的时候会关闭一些服务器,流量大的时候会不断的开启新的服务器。65535是从哪里来的,它有什么作用?要很好地解释这个问题,首先要弄清楚65535的含义。在Linux系统中,两台机器如果要进行通信,需要相互建立TCP连接。Linux系统为了让双方互相认识,使用四元组来唯一标识一个TCP连接:{localip,localport,remoteip,remoteport},即localIP,localport,remoteIP,和远程端口。IP和端口相当于小区的地址和门牌号。只有有了这些信息,通信的双方才能相互识别。在Linux系统中,代表端口号(port)的变量占16位,决定了最多有端口号的2的16次方,即65536。另外,端口0有特殊意义,没有使用,这样每台服务器最多有65535个端口可用。所以65535代表Linux系统支持的TCP端口号的个数,TCP建立连接时会用到。TCP如何建立连接,与端口号有什么关系?Linux服务器交互时,一般有两种身份:客户端或服务器。典型的交互场景是:(1)服务端主动创建监听socket,绑定对外服务端口port,然后开始监听(2)当客户端要与服务端通信时,开始连接服务端端口port(3)服务器接受客户端的请求,然后生成一个新的套接字(4)服务器和客户端在新的套接字中进行通信。可以看出,port端口主要用在服务端和客户端的“握手识别”过程中。一旦它们相互认识,就会生成一个新的套接字用于通信。这时候该端口就不再需要了,可以用于其他socket通讯,所以显然TCP连接数可以大于TCP端口号65535的数量。考虑两种极端的场景,即某台Linux服务器只作为客户端或者服务器(1)Linux服务器只作为客户端。此时每发起一个TCP请求,系统都会指定一个空闲的本地端口供你使用,并且是独占的,不会被其他TCP连接抢夺,所以最多可以建立65535个连接,并且每个连接都与不同的服务器交互。这种场景正是题主所描述的,但是因为条件过于苛刻,属于小概率事件,所以理论上比较有可能,在真实环境中几乎不会出现。(2)在linux服务器只作为服务端的场景下,服务端会固定监听本地端口端口,等待客户端向它发起请求。为了计算简单,我们假设服务器的IP和端口是多对一的,这样TCP四元组中的remoteip和remoteport是可变的,所以最大支持的TCP个数是2到32的次方(IP地址为32位)乘以2的16次方(端口为16位)等于2的48次方。现实中单台Linux服务器支持的TCP连接数通过前面的分析我们知道,在现实场景中,由于端口复用,一台服务器所能支持的TCP连接数之间并没有一一对应关系同时和65535。实际上,真正影响TCP连接数的是服务器的内存和单个进程同时允许打开的文件数,因为每次TCP连接都是创建时,会创建一个套接字句柄,每个套接字句柄占用一部分系统内存。当系统内存被占用Exhausted时,允许的TCP并发连接数达到上限。一般来说,通过增加服务器内存,修改最大文件描述符数等方式,单台服务器可以支持10万+的TCP并发。当然,在真正的商业场景中,会把单台服务器编入分布式集群,通过负载均衡算法将不同用户的请求动态调度到最空闲的服务器上。如果服务器平均内存使用率超过80%的警戒线,那么我们会及时采取限流或者扩容的方式来保证服务,绝不会出现服务器内存耗尽的情况,所以会视为意外。总之,65535只是Linux系统可以使用的端口数的上限。端口数和TCP连接数之间并不是一一对应的。服务器支持的TCP并发连接数主要与服务器的内存和允许单个进程同时打开的文件数有关。通过端口复用和调整服务器参数,可以使单台服务器支持的TCP并发连接数高于65535。
