TCP(Transmission Control Protocol)
面向连接、可靠的、基于字节流的传输层通信协议
特点
基于连接:数据传输之前需确保连接已正常建立
双全工:支持双向数据传输
字节流:不限制数据大小,统一打包成报文段,保证有序接受,重复保温自动舍弃
流量缓冲:说是解决双方处理能力的不匹配(个人理解就是怕在接受数据的时候,接收端处理不过来会先放到缓存区)
可靠的传输服务:保证数据可达,丢包后可通过重发机制实现可靠性
拥塞控制:防止网络出现恶性拥塞
数据结构
| 名称 | 含义 | 大小 |
|---|---|---|
| Source port | 数据来源端口 | 16bit |
| Dest prot | 数据目的端口 | 16bit |
| Squence number | 数据序列号 | 32bit |
| Acknowledge number | 确认号 | 32bit |
| Header length | 头部长度 | 4bit |
| Unuse | 保留位 | 6bit |
| URG | 紧急指针位(当URG=1时,表明紧急指针字段有效。它告诉系统此报文段中有紧急数据,应尽快传送(相当于高优先级的数据)。) | 1bit |
| ACK | 确认位(当ACK=1时,确认号才有效) | 1bit |
| RST | 重置位(当RST=1时,表明TCP连接中出现严重差错(如由于主机崩溃或其他原因),必须释放连接,然后再重新建立运输连接。一般在三种情况下出现:拒绝连接请求、异常终止连接、终止空闲连接。) | 1bit |
| SYN | 同步位(当SYN=1时,表示这是一个连接请求或连接接收报文) | 1bit |
| FIN | 终止位(当FIN=1时,表示报文段的发送端已接发送完毕,要求释放运输连接) | 1bit |
| Receive window | 接受窗口大小 | 16bit |
| Internet checksum | 校验位 | 16bit |
| Urgent data pointer | 紧急指针 | 16bit |
| Options | 可选数据域 | 长度可变 |
| Data | 负载数据 | 长度可变 |
TCP连接
tcp主要四元组[源地址、源端口、目的地址、目的端口]
通过三次握手确定连接
三次握手
客户端与服务端建立连接交互确定需3个数据包,故此称为三次握手;握手主要确定双方接收和发送数据的能力是否正常。

- 客户端发起SYN报文,进入SYN_SENT状态,等待服务端确认
- 服务端收到SYN报文,需给客户端发送ACK确认报文,同时服务端也需向客户端发送一个SYN报文,即服务端发送的报文为SYN+ACK报文,同时服务端进入SYN-RECEIVED
- 客户端收到SYN+ACK报文,向服务端发送确认包,客户端进入ESTABLISHED状态;服务端在收到客户端的ACK包后也会进入ESTABLISHED状态,及完成三次握手。
二次握手可以吗?
为什么一定要是三次握手,二次握手可以吗?
确定双方通信能力
第一次握手:客户端发送数据包,服务端接收到后,服务端可确定客户端发送能力、服务端接受能力没有问题
第二次握手:服务端发送数据包,客户端收到后,客户端可确定客户端发送、接受;服务端发送、接受能力没有问题(此时服务端无法确定客户端接收能力是否正常)
第三次握手:客户端发送数据包,服务端收到后,服务端可确定客户端发送、接受;服务端发送、接受能力没有问题
阻止重复的历史链接
在发起连接时如果客户端第一次发送的连接请求,在网络传输过程中某个节点滞留,导致客户端再次发送一次连接请求,并确定建立了链接;这时因某个节点导致滞留的请求又到达服务端,如果没有三次握手,服务端会认为这是一个新的连接,造成网络异常。
三次握手可以携带数据吗
第一次及第二次握手不可携带数据,第三次握手可携带数据
如在第一次握手时客户端发起恶意请求,携带大量数据请求,服务器需消耗资源来处理这些数据,导致资源的占用。
在第三次握手时可以携带是因,已经经过俩次握手确定了客户端已经确定服务端的接收和发送能力没有问题,客户端已经处于连接状态,已经知晓服务端接受、发送能力正常,所以可以携带数据请求
四次挥手

- 客户端发起FIN包,客户端进入FIN_WAIT_1状态;(TCP规定,即FIN包补携带数据,也要消耗一个序号)
- 服务端收到FIN包,发出确认包ACK(ack=u+1),并带上自己的序号(seq=v),服务端进入CLOSE_WAIT状态。这时客户端已经没有数据要发送了,不过服务端如果有数据发送,客户端需正常接收;客户端接收到服务端的ACK后,进入FIN_WAIT_2状态
- 服务端发送完毕后,向客户端发送FIN包(seq=w,ack=u+1),半连接状态下服务端可能又发送了一些数据,假设seq=w。服务器此时进入LAST_ACK状态
- 客户端收到服务端FIN包后,发出确认包(ACK=1,ack=w+1),此时客户端就进入了TIME_WAIT状态(此时连接还未释放,需经过2*MSL后才进入CLOSE状态)。服务端在收到客户端的ACK包后就直接进入CLOSED状态。
为什么建立连接是三次,关闭却需要四次
在三次握手时,SYN+ACK包是将一个ACK和一个SYN合并到一个包中,减少了一次报的发送,三次完成握手
四次挥手,因TCP是全双工通信,在发起关闭方发送FIN包后,接收到可能还需要发送数据,不能立即关闭服务端到客户端的通信,所以就不能将服务端的FIN包和对客户端的ACK包合并发送,只能先确认ACK,然后服务端带无需发送数据时发送FIN包,所以四次挥手时必须是四次数据包交互
为什么是TIME_WAIT状态需要经过2MSL才能到CLOSE状态
MSL为报文最大生存时间,在客户端发送对服务端的FIN包的确认ACK包后,这个ACK包是有可能不可达的,服务端如果收不到ACK的话需要重新发送FIN包。
所以客户端发送 ACK 后需要留出 2MSL 时间(ACK 到达服务器 + 服务器发送 FIN 重传包,一来一回)等待确认服务器端确实收到了 ACK 包。
也就是说客户端如果等待 2MSL 时间也没有收到服务器端的重传包 FIN,说明可以确认服务器已经收到客户端发送的 ACK。
还有第 2 个理由,避免新旧连接混淆。
在客户端发送完最后一个 ACK 报文段后,在经过 2MSL 时间,就可以使本连接持续的时间内所产生的所有报文都从网络中消失,使下一个新的连接中不会出现这种旧的连接请求报文。
你要知道,有些自作主张的路由器会缓存 IP 数据包,如果连接重用了,那么这些延迟收到的包就有可能会跟新连接混在一起。
参考链接:https://www.eet-china.com/mp/a44399.html
停止等待协议
发送一组数据包,等到接收端响应后再发送下一组数据包
该效率简单直白,但导致带宽利用率过低,一次只发送一条消息,导致带宽大部分资源空闲
上图表示数据在传输中无差错的情况,接收方在规定时间内收到,并回复确认
停止等待协议超时
发送报文丢失:如发送端报文丢失,导致接收端未收到报文,此时在发送端超过指定时间后未接收到确认,则认为发出的报文丢失,进而重新发送
ACK丢失:在发送端发送报文后,接收到接收到报文,发送出ACK(确认报文)时,消息丢失导致发送端未接收到确认报文;在发送端超过指定时间未接收到确定报文,则认为发出的报文丢失,进而重新发送
传输延迟:发送方发送成功,接收方接收成功,但因网络延迟,超过发送方设置超时时间,发送方即会重新发送报文,此时接收方要做的事情,丢弃报文,重新发送ACK(确定报文),发送如果收到俩个或多个确认,停止发送
滑动窗口协议与累积确认
滑动窗口大小怎么确定
接收端是否知道发送方会发送多少窗口大小

参考:[https://cloud.tencent.com/developer/article/1857363](




浙公网安备 33010602011771号