目录
1.TCP协议格式
- 源/目的端口号:表示数据是从哪个进程来,到那个进程去。
- 4位TCP报头长度:表示该TCP头部有多少个3位bit,所以TCP头部最大长度是15*4=60
- 6位标志位:
- URG:紧急指针是否有效。
- ACK:确认号是否有效。
- PSH:提示接收端应用程序立刻从TCP缓冲区把数据读走。
- RST:对方要求重新建立连接,我们把携带RST标识的称为复位报文段。
- SYN:请求建立连接;我们把携带SYN标识的称为同步报文段。
- FIN:通知对方,本端要关闭了,我们称携带FIN标识的为结束报文段。
- 16位窗口大小
- 16位校验和:发送端填充,CRC校验。接收端校验不通过,则认为数据有问题,此处的检验和不光包含TCP首部,也包含了TCP数据部分。
- 16位紧急指针:标识那部分数据是紧急数据
- 40字节头部选项
2.TCP协议的特点
有连接,可靠传输,面向字节流,全双工方式
3.TCP协议的核心机制(十个)
3.1确认应答机制
TCP要解决一个很重要的问题——可靠传输。并不是说发送方能够100%的把数据传给接受方。但是会尽可能的让发送方知道接收方是否收到。
对每个字节的数据都进行了编号,即序列号。
每一个ack都带有对应的确认序列号,意思是告诉发送者,我已经收到了那些数据;下一次你从哪里开始发。
3.2超时重传
- 主机A发送数据给B之后,可能因为网络拥堵等原因,数据无法到达主机B。
- 如果主机A在一个特定时间间隔内没有收到B发来的确认应答,就会进行重发。
但是,主机A未收到主机B发来的确认应答,也可能因为ACK丢失了。
因此,主机B会收到很多的重复数据,那么TCP协议需要能够识别出那些包是重复的包,并且把重复的丢弃掉。
超时的时间如何确定?
- 最理想的情况下,找到一个最小的时间,保证“确认应答一定能在这个时间内返回”。
- 但是如果这个时间的长短,随着网络环境的不同,是有差异的。
- 如果超时的时间设定的太长,会影响整体的重传效率。
- 如果超时时间设定的太短,有可能会频繁的发送重复的包。
TCP为了保证无论在任何环境下都能比较高性能的通信,因此会动态计算这个最大超时时间。
3.3连接管理
1.包含两部分(1)建立连接流程:三次握手。
发送一个不携带业务数据的数据报。
(2)断开连接:四次挥手。
2.建立连接实际上就是通信双方,各自保存对端的信息(三次网络交互)
三次握手发生在传输业务之前,握手好了才能进行后续的传输。
3.3.1三次握手基本流程:
- 第一次:客户端给服务器:SYN同步报文。(这个数据报不携带业务数据载荷为空,只有TCP报头,6个标志位中的SYN为1)。
- 第二次:服务器给客户端的ACK应答报文和SYN的同步报文合并成一次。
- 第三次:客户端给服务器的ACK应答报文。
上述流程就是客户端和服务器各自给对方发送syn,在各自给对方回一个ACK。
双方各自在让对方保存自己的信息,此时建立完成。
相当于可靠传输的一种保证方式(辅助)。核心是确认应答和超时重传。
3.3.2三次握手的意义或者解决的问题:(面试题)
(1)三次握手相当于“投石问路”,在正式传输业务数据之前,先确认一下通信链路是否畅通。
(2)通过三次握手,确认通信双方,发送能力和接受能力都是正常的。
如果三次变两次变四次是否可行?(面试题)
两次:不可行,此时服务器对于发送能力和接受能力认知是不完整的,需要三次交互才能把客户端掌握的完整情况,告知给服务器。
四次:可行,但是没必要。
(3)三次握手过程中,还需要协商一些必要的参数。
通信双方共同协商一下,有的参数不是单方面确认的需要双方共同来确认出来的。
TCP通信时使用的信号,就是协商出来的。
序号往往不是从0/1开始的,而是三次握手时,通信上方协商出来的一个数字。
每次建立的连接都是一个新的数字,作为起始的序号,差别很大的直接丢弃,防止不同的干扰。
3.3.3三次握手时TCP的状态
- LISTEN:服务器会出现的状态,当服务器绑定端口成功后进入。意味着随时可以有客户端连接上来。
- ESTABLED:建立完成,客户端和服务器都有;意味着随时可以进行后续通信了。
3.3.4断开连接:四次挥手
和三次挥手区别:三次握手一定是客户端发起的第一次请求;四次挥手客户端和服务器都可以主动发起。
3.3.5四次挥手的流程:
以客户端发起为例:
- 第一次:客户端给服务器一个FIN结束报文(客户端代码中调用Socket.close方法或者客户端进程结束)(FIN是第六个标志位中的第六位)。
- 第二次:服务器给客户端一个ACK(应答报文)。
- 第三次:服务器给客户端一个FIN(结束报文)。
- 第四次:客户端给服务器一个ACK(应答报文)。
断开连接实际上就是双方把之前保存的对方信息删除。
四次挥手中间的两次是否能合并?
面试时问到可不可以回答特殊情况下是可以的。
常规下是不可以的。
三次挥手可以合并是因为SYN和ACK都是内核自动控制发送的(同一时机)。
四次挥手的ACK是内核控制的;FIN是应用程序代码中调用close的时候才会触发的(应用程序控制的不是同一时机(相距时间较长))
特殊情况下是可以的。
TCP中的一个机制——延时应答(不用立刻回复ACK,可以等一会儿)。
3.3.6四次挥手时TCP的状态转换
(1)CLOSE_WAIT:被动一方进入的状态,等待代码调用close。调用越及时越不容易被看到。
如果出现大量的CLOSE_WAIT,则说明代码大概率会有bug了。
(2)TIME_WAIT:主动一方进入的状态,
应对最后一个ack丢包的情况。
客户端在收到服务器的fin之后,不能立即释放Tcp连接。(如果立即释放了,后续一旦对端重传fin,此时,客户端就无法应对了)。
不是持续的,而是有一定的时间的。
在一定时间之内,如果没有收到重传的fin,那么最后一个ack已经被对方收到了,就不会重传fin。