什么是TCP
tcp是面向连接的、可靠的、基于字节流的传输协议
- 面向连接:一定是一对一的才能连接,不能像udp一样可以一个主机同时向多个主机发送消息
- 可靠的:无论网络链路中出现什么链路变化,TCP都可以保证一个报文一定能到达接收端
- 字节流:消息是「没有边界」的,所以无论我们消息有多大都可以进行传输。并且消息是「有序的」,当「前一个」消息没有收到的时候,即使它先收到了后面的字节已经收到,那么也不能扔给应用层去处理,同时对「重复」的报文会自动丢弃。
TCP头部信息
三次握手

- 客户端会随机一个初始化序号(client_isn),将此序号置于TCP首部的【序列号】字段中,同时把SYN标志位置为1,标识SYN报文
- 服务端收到客户端报文后,服务端也随机生成一个序号(server_isn),将此序号置于TCP首部的【序列号】字段中,接着把【确认应答号】字段填入client_isn +1,把SYN和ACK标志为1
- 客户端收到服务端的报文后,将新报文中的ACK标志为1,将【确认应答号】字段填入server_isn+1,这次报文是可以携带数据的
Q:为什么第三次握手可以携带数据
A:因为第三次握手服务端接受到后双方都变为ESTABLISHED状态,此时连接就建立完毕了
Q:为什么是三次握手,不是两次、或者四次
A:
- 避免历史连接,防止旧的重复连接初始化造成混乱。(主要原因)

如果是两次握手就不能判断当前连接是否是历史连接,三次握手则可以再发送第三次报文时,根据上下文判断是否是重复连接,然后选择发送RST报文终止连接还是ACK确认连接
- 三次握手才可以同步双方的初始序列号

四次握手其实也能够可靠的同步双方的初始化序号,由于第二步和第三步可以优化成一步,所以就成三次握手
- 三次握手才可以避免资源浪费

客户端超时重发,会造成资源浪费
四次挥手

- 客户端打算关闭连接,此时会发送一个 TCP 首部
FIN标志位被置为1的报文,也即FIN报文,之后客户端进入FIN_WAIT_1状态。 - 服务端收到该报文后,就向客户端发送
ACK应答报文,接着服务端进入CLOSED_WAIT状态。 - 客户端收到服务端的
ACK应答报文后,之后进入FIN_WAIT_2状态。 - 等待服务端处理完数据后,也向客户端发送
FIN报文,之后服务端进入LAST_ACK状态。 - 客户端收到服务端的
FIN报文后,回一个ACK应答报文,之后进入TIME_WAIT状态 - 服务器收到了
ACK应答报文后,就进入了CLOSE状态,至此服务端已经完成连接的关闭。 - 客户端在经过
2MSL一段时间后,自动进入CLOSE状态,至此客户端也完成连接的关闭。
Q:为什么是四次挥手
A:
- 客户端向服务端发送FIN报文时,只是代表不发送消息了,但是还可以接收消息
- 服务端在接收到FIN报文时,发送ACK确认消息,但可能还有数据没有处理完,所以要等服务端不再发送消息了,才能发送FIN报文
所以服务端的FIN报文和ACK报文要分开发送,比三次握手多了一次,所以是四次挥手
Q:为什么TIME_WAIT时间是2MSL
A:
- TCP报文时基于IP协议的,IP头中有一个TTL字段,是IP数据包可以经过的最大路由,每经过一个路由就递减1,当减到0的时候数据将别丢弃,同时发送ICMP报文给源主机
- MSL是报文最大生存时间,超过这个时间报文将被丢弃,所以MSL应该大于等于TTL消耗为0的时间,以确保报文被自然消亡
TIME_WAIT是2MSL的原因是:
- 服务端发送FIN报文给客户端,客户端接受到FIN报文后开始发送ACK报文给服务端,假如服务端没有接受到 ACK报文就会超过一个MSL超时重发FIN报文
- 客户端再发送一个ACK报文,如果一个MSL没有收到再重发的FIN报文,就算断开连接成功,这么一来一回正好2MSL
确认重传机制

A和B确认连接后,每次A发送消息都会带上SeqNo,并且B在接收后,返回给Ack消息,AckNo=(SeqNo+报文字节数),如果A一个超时时间没有收到ACK消息,则会重传
滑动窗口

- 普通的一个请求一个ack太慢,可以一次发送多条数据,窗口大小决定了可以发送多少数据,上图窗口为4000,这个窗口值是根据接收方的缓存区大小决定的
- 当主机A收到5001的应答,但未收到3001、4001的应答时,我们可以考虑两种情况,但是都不影响,因为可以确定5001之前的数据都被接收到了
- 3001、4001的应答较慢,5001的应答较快,所以先到达;
- 3001、4001的应答丢失了;
- 如果出现丢包怎么处理,有两种情况
- 数据到了,Ack丢失,可以通过后续的Ack来确认
- 数据包直接丢了,接受端会一直发送1001的ack,当发送超过3次,就会触发重传
流量控制

接受端处理速度是有限的,TCP支持根据接收端的处理能力,来决定发送端的发送速度,这个机制就叫做流量控制
延迟应答
如果接收到数据没有充满窗口,就会延迟应答,这样就可以充分利用窗口大小
但是也不是所有的包都延迟应答,会受到数量限制和时间限制,数量就是没隔N个包就应答一次,没隔多长时间就应答一次,一般N为2,时间为200ms
