大家好,我是老杨。
在知乎上刷到一个问题,叫做“一台主机上只能保持最多 65535 个 TCP 连接吗?”
关注度极高,想着咱们粉丝也一定有兴趣,就展开聊一聊。
对技术感兴趣,是做我们这一行必须要有的品质之一,但对技术有执念,想要一个个学深学透,是优秀的网工才会有的特点。
如果你对技术有着无限热情,建议看一看我专门为我的粉丝整理过的网络技术图谱。
其中包括了网络技术必学的技术方向和细分类目,告诉你一个技术得学,还告诉你要从哪几个方面学。
私信我,发送暗号“网络技术”,即可获取,算是福利一波。
01 趣说TCP那些事
说回正题,在聊这个问题之前,我需要先给小白们搞定一下基础概念。
到底什么是TCP?
你去随便百度一下,你就会收获到这一段话:
“TCP传输控制协议(Transmission Control Protocol)是一种面向连接的、可靠的、基于字节流的传输层通信协议,由IETF的RFC 793定义。”
看的云里雾里不要紧,我们转换成人话就能听上一听。
如果你想要和女朋友24小时联系,永远不分开,你就需要一个东西把你俩千里姻缘一线牵起来。
这个东西,可能是麻绳,可能是月老的红绳,可能是电话线,也可能是TCP协议。
TCP是面向连接的,也就是说,TCP的目的就是为了连接A和B,在这个层面上,它起到了“连接”作用。
如果仅仅是“连接”,还不能满足你和你女朋友“24小时联系,永远不分开”的要求。
毕竟,可能这绳子质量不好给整断了,月老一个不开心把你俩红绳给拆了,又或者是电话没信号了,都会影响你的稳定性需求。
那这时候,用TCP连接,就不会有这个问题,因为TCP连接的过程很坎坷,正因为坎坷,所以十分“可靠”。
这就是被人耳熟能详的“三次握手”、“四次挥手”。
网络环境十分复杂,接受的是来自四面八方全方位的包,将其送到准确的目的地,还要保证稳定的连接,是件很难的事情。
为了实现这个愿望,TCP不得不煞费苦心的经过3+4的握手挥手,保证一个数据顺利传递到对方那里。
从某个层面来说,山盟海誓都不如TCP传输的可靠性来的有价值。
最后,TCP的连接传输是基于字节流的,这句话怎么理解?
要知道哈,通过TCP发送出去的消息,是被操作系统拆分成一个一个的报文来发送的。
报文的内容不是完整的,要等所有的报文都到位,进行组装后,你才能收到一个完整的信息,最后让女朋友看到那句:“我好想你啊,出来吃饭吧!”
那么,TCP连接如此复杂,一台主机上真的能保持最多 65535 个 TCP 连接吗?
继续往下看。
02 TCP连接到底有啥弯弯绕绕的?
简单介绍完了TCP,你或许对TCP和他的连接方式产生了兴趣。
这里需要再给你延展两个概念,一个是第一点提及的“三次握手”,第二个“TCP四元组”,帮助我们更好回答文章开头的技术问题。
01 三次握手,怎么握的?
TCP的“三次握手”你可以理解为是TCP发功时所需要的仪式。
因为TCP常常用来发送大批量的数据,所以,为了提供可靠的的传送服务,TCP在发送数据之前,都需要用一种特定的顺序将数据包编号,并将这些数据包传送给目标,再确认消息。
当对应的程序收到数据后,确认收到也需要用到TCP。
其实,三次握手就是为了对每次发送的数据量进行跟踪与协商,确保数据段的发送和接收同步,根据所接收到的数据量而确认数据发送、接收完毕后何时撤消联系,并建立虚连接。
那说了半天,到底握手是怎么握?
Step 1
TCP客户端准备发送一个syn段,用来指明客户打算链接的服务器端口以及isn(初始序号)。那么这个syn就被称为“报文段1”。
Step 2
那么,接下来,TCP服务端就会发回包含TCP服务端isn的syn段(即报文段2)作为回应。与此同时,TCP服务端会将确认序号设置为TCP客户端的isn+1,以对TCP客户端的s y n报文段进行确认。
Step 3
最后,TCP客户端也必须将确认的序号设置为TCP服务端的isn+1,作为对TCP服务端syn报文段的确认(即报文段3)这三个报文段就代表了连接的建立,而这个过程,就是TCP的三次握手(three-wayhandshake)。
谢希仁版的《计算机网络》里说过,TCP的握手,其实是为了保证双方互相明确对方收发能力的最低值。两次太少,四次太多,三次正正好。
而且啊,其实不论握手多少次都不能确认一条信道是“可靠”的,但通过3次握手可以至少确认它是“可用”的,再往上加握手次数,其实就不过是提高“它是可用的”这个结论的可信程度。
而且严格来说,三次握手其实是双方各握手一次,然后各确认一次,其中,一次握手+确认是合并在一起的,这才是“三次”的由来。
02 TCP四元组
如何唯一确定一个 TCP 连接,这就不得不提到TCP 四元组这个概念,它可以唯一的确定一个连接。
到底啥是TCP四元组?
四元组包括:源地址、源端口、目的地址、目的端口。
其中,源地址和目的地址的字段(32 位)是在 IP 头部中,作用是通过 IP 协议发送报文给对方主机。
源端口和目的端口的字段(16 位)是在 TCP 头部中,作用是告诉 TCP 协议应该把报文发给哪个进程。
通过TCP四元组,你才能标识到一个TCP连接数:{localip, localport,remoteip,remoteport} = {本地ip,本地port,远程ip,远程port}
所以,整体过程应该是:
server事先在某个固定端口监听,client主动发起连接,经过三次握手后建立tcp连接。
接下来,确定了单位值,也确定了连接过程,我们就可以推算到底标题中的数字对还是不对了。
03 一台主机上只能保持最多 65535 个 TCP 连接吗?
先从这句话的字面意思去剖析,答案肯定是错误的。
因为,1个IP可能的确最多只能65535个连接,但是一台主机可以有多个IP,所以这句话本身是有一定歧义的。
再者,我们来聊这个65535次的问题。
要解释好这个问题,就要先说清楚65535这个数字到底从哪里来的。
在Linux系统中,如果两个设备要通信,相互之间就得建立TCP连接,为了让双方互相认识,Linux系统需要用TCP四元组来唯一标识一个TCP连接。
IP和端口就相当于小区地址和门牌号,只有拿到这些信息,通信的双方才能互相认知。
在Linux系统中,表示端口号(port)的变量占16位,这就决定了端口号最多有2的16次方个,即65536个,另外端口0有特殊含义不给使用,这样每个服务器最多就有65535个端口可用。
所以,65535代表Linux系统支持的TCP端口号数量,在TCP建立连接时会使用。
但是,一般的系统里 1024 以下的端口都是保留的,所以没法用。可用的大约就是64000个。
这仅仅是端口数量,和连接数是有区别的,实际上客户端可以发出的连接远远不止这个数。
Linux服务器在交互时,一般有两种身份:客户端或者服务器端。
端口port主要用在服务器和客户端的“握手认识”过程,一旦互相认识了,就会生成新的socket进行通信。
这时候port就不再需要了,可以给别的socket通信去使用,所以很明显TCP连接的数量可以大于TCP端口号的数量65,535。
客户端 IP 和 端口是可变的,理论值计算公式就是:最大TCP连接数=客户端的IP数 x 客户端的端口数
对 IPv4,客户端的 IP 数最多为 2 的 32 次方,客户端的端口数最多为 2 的 16 次方,也就是服务端单机最大 TCP 连接数,约为 2 的 48 次方。
当然,服务端最大并发 TCP 连接数远不能达到理论上限,会受很多因素影响,比如文件描述符限制和内存限制等。
看到这里,你是否有所收获?
如有自己的见解,也欢迎留言分享给更多网工朋友。
原创:老杨丨10年资深网络工程师,更多网工提升干货,请关注公众号:网络工程师俱乐部