- 1. TCP 头部
- 2. 可靠传输的基本原理
- 3. TCP协议的可靠传输
- 4. TCP协议的流量控制
- 5. TCP协议的拥塞控制
- 6. TCP连接的三次握手
- 7. TCP连接的四次挥手
- 8. TCP 小结
# TCP
TCP(Transmission Control Protocol
),又叫传输控制协议。 TCP 协议是面向连接的,可靠的,基于字节流的传输协议。
在基于 TCP 进行通信时,通信双方需要先建立一个 TCP 连接,建立连接需要经过三次握手,断开连接的时候需要经过四次挥手。
# 1. TCP 头部
TCP协议头部,固定20个字节,UDP头部只有8个字节,IP协议头部20个字节:
对于 TCP 头部来说,以下几个字段是很重要的:
序列号
(Sequence number
)0~ 2^32-1
- 一个字节一个序号
- 数据首字节序号(第一个字节)
- 这个序号保证了 TCP 传输的报文都是有序的,对端可以通过序号顺序的拼接报文
确认号
(Acknowledgement Number
)- 这个序号表示数据接收端期望接收的下一个字节的编号是多少,同时也表示上一个序号的数据已经收到
- 确认号为N:表示N-1序号的数据都已经收到,比如,收到了序号为501的数据报,长度是100,下一次确认号则为601
窗口大小
(Window Size)- 表示还能接收多少字节的数据,用于流量控制
- 数据偏移
- 占4位:0~15,单位为:32位字(由此可以看出最大偏移为
15*4
,即TCP首部长度介于20-60个字节之间) - 数据偏离首部的距离
- 不知道TCP选项有多长,所有用数据偏移表示真实的数据离头部偏移有多少
- 占4位:0~15,单位为:32位字(由此可以看出最大偏移为
标识符
ACK=1
:该字段为一表示确认号字段有效。此外,TCP 还规定在连接建立后传送的所有报文段都必须把 ACK 置为一。SYN=1
:当 SYN=1,ACK=0 时,表示当前报文段是一个连接请求报文。当 SYN=1,ACK=1 时,表示当前报文段是一个同意建立连接的应答报文。FIN=1
:该字段为一表示此报文段是一个释放连接的请求报文。URG=1
: 该字段为一表示本数据报的数据部分包含紧急信息,是一个高优先级数据报文,此时紧急指针有效。紧急数据一定位于当前数据包数据部分的最前面,紧急指针标明了紧急数据的尾部。PSH=1
:该字段为一表示接收端应该立即将数据 push 给应用层,而不是等到缓冲区满后再提交。RST=1
:该字段为一表示当前 TCP 连接出现严重问题,可能需要重新建立 TCP 连接,也可以用于拒绝非法的报文段和拒绝连接请求。
- 紧急指针
- 紧急数据(URG=1)
- 指定紧急数据在报文的位置
- TCP选项
- 最多40字节(60-20)
- 支持未来的拓展
# 2. 可靠传输的基本原理
停止等待协议:
- [ ] 发送方等待接收方的确认消息,才发送新的信息
- [ ] 最简单的可靠传输协议
- [ ] 通过超时重传保证可靠传输
- [ ] 对信道的利用效率不高
停止等待协议,无差错的情况:
出差错的情况,超时重传,包括接收方没有收到发送方的消息:
超时重传,发送方没有收到接收方的确认信息:
超时重传,确认消息很久才收到:
小结:
- [ ] 发送的消息在路上丢失了
- [ ] 确认的消息在路上丢失了
- [ ] 确认的消息很久才到
停止等待协议通过超时重传保证可靠传输
超时定时器:
- [ ] 每发送一个消息,都需要设置一个定时器
# 2.1. 连续ARQ协议
- [ ] ARQ(
Automatic Repeat reQuest
)自动重传请求 - [ ] 批量发送和确认
- [ ] 滑动窗口和累计确认是其两个重要概念
滑动窗口,收到前面的确认消息,滑动窗口向前移动,把滑动窗口内的未发送消息发送出去:
并不需要对每一个报文都确认,而采用累计确认的方法。如收到了5的确认消息,则认为1-5的消息都已经收到了,就把滑动窗口往前移动5格:
# 3. TCP协议的可靠传输
- [ ] TCP的可靠传输基于连续ARQ协议
- [ ] TCP滑动窗口以字节为单位
滑动窗口里面的7个字节都是可以发送的,左边是已经确认的字节序号,右边是不允许发送的字节序号,窗口内最左边是对方期待收到的下一个字节
窗口内又可分为已发送未确认和可用窗口,由于没收到前面的确认所以不能往前移动:
有可能窗口内都是已发送未确认,可用窗口=0。
没有按序收到确认消息,即收到后面的确认消息,但是没收到前面的,超时后,会从前面开始重传,效率低:
选择重传:
- [ ] 选择性的重传某些消息,而不是重传所有消息
- [ ] 选择重传需要指定需要重传的字节
- [ ] 每一个字节都有唯一的32位序号
TCP选项最多40个字节(60-20),即最多10个序号,指定的是需要重传的边界,而不是字节,表明需要重传的一段范围
一段一段,如果里面存了1000和1500,指的是需要重传1000~1500
这一段数据,
# 4. TCP协议的流量控制
- 特有的功能(UDP和其他协议没有)
- 流量控制指让发送方发送速率不要太快
- 流量控制是使用滑动窗口来实现的(确认号是
501
的话,如果窗口是1000
,表明接收方希望接收501-1501
的数据)
通过窗口大小控制对方发送速率:
如果丢失了最后的确认窗口变大(不为0)的消息,就会导致死锁,发送方一直等到对方窗口变大,接收方一直等待对方发送消息
坚持定时器(解决死锁):
- [ ] 当发送方接收到窗口为0的消息,则启动坚持定时器
- [ ] 坚持定时器每隔一段时间发送一个窗口探测报文
这种死锁相当于情侣一方A一直等待对方B改变脾气,而B已经改变了,但联系不到A,坚持定时器是A每隔一段时间问一下B,你改变了没有。
# 5. TCP协议的拥塞控制
- [ ] 一条数据链路经过非常多的设备
- [ ] 数据链路中各个部分都有可能成为网络传输的瓶颈(导致拥塞)
注意:
- [ ] 流量控制考虑点对点的通信量的控制
- [ ] 拥塞控制考虑整个网络,是全局性的考虑
- [ ] 报文超时则认为是拥塞(虽然不一定)
慢启动算法:
- [ ] 由小到大逐渐发送数据量
- [ ] 每收到一个报文确认,就加一(指数增长,1 2 4 8 16…)
- [ ] 增长到慢启动阈值(
ssthresh
)后就不增长了
拥塞避免算法:
- [ ] 维护一个拥塞窗口的变量
- [ ] 只要网络不拥塞,就试探着把拥塞窗口调大(比如到了慢启动阈值
16
后,以后发送17、18、19…
个报文)
二者结合,先进行慢启动算法,再进行拥塞避免算法:
上述过程就像一个人贪婪的过程
# 6. TCP连接的三次握手
简单的说:
- 第一次握手
SYN = 1, seq(client) = x
- 客户端向服务端发送连接请求报文段。该报文段中包含自身的数据通讯初始序号。请求发送后,客户端便进入
SYN-SENT
状态。
- 第二次握手
SYN = 1,ACK = 1,ack(确认序号) = x+1, seq(server) = y
- 服务端收到连接请求报文段后,如果同意连接,则会发送一个应答,该应答中也会包含自身的数据通讯初始序号,发送完成后便进入
SYN-RECEIVED
状态
- 第三次握手
ACK = 1,ack(确认序号) = y+1, seq(client) = x + 1
- 客户端收到连接同意的应答后,还要向服务端发送一个确认报文。客户端发完这个报文段后便进入
ESTABLISHED
状态,服务端收到这个应答后也进入ESTABLISHED
状态,此时连接建立成功。
为什么发送方要发出第三个确认报文(为什么需要第三次握手)?
- 防止已经失效的连接请求报文传送到对方,引起错误
举例:
- [ ] 发送方第一次握手时发送很久没有收到对方应答,于是发送了第二封,第二封比第一封更早到达,第一次便是失效的请求报文
- [ ] 如果两次握手就能建立起连接:同一个请求发送两次(第一次超时)就会建立起两个连接,引起错误
- [ ] 本来这是一个早已失效的报文段,但
server
收到此失效的连接请求报文段后,就误认为是client
再次发出的一个新的连接请求。
虚线是假设两次握手就建立连接
# 7. TCP连接的四次挥手
比三次握手多出来的是第二次挥手,意思是我收到了,但是我现在还没传完,等会关闭
TCP 是全双工的,在断开连接时两端都需要发送 FIN 和 ACK。
- 第一次挥手
- 若客户端 A 认为数据发送完成,则它需要向服务端 B 发送连接释放请求。
- 第二次挥手
- B 收到连接释放请求后,会告诉应用层要释放 TCP 链接。然后会发送 ACK 包,并进入 CLOSE_WAIT 状态,表示 A 到 B 的连接已经释放,不接收 A 发的数据了。但是因为 TCP 连接时双向的,所以 B 仍旧可以发送数据给 A。
- 第三次挥手
- B 如果此时还有没发完的数据会继续发送,完毕后会向 A 发送连接释放请求,然后 B 便进入LAST-ACK状态。
- PS:通过延迟确认的技术(通常有时间限制,否则对方会误认为需要重传),可以将第二次和第三次握手合并,延迟 ACK 包的发送。
- 第四次挥手
- A 收到释放请求后,向 B 发送确认应答,此时 A 进入 TIME-WAIT 状态。该状态会持续 2MSL(最大段生存期,指报文段在网络中生存的时间,超时会被抛弃) 时间,若该时间段内没有 B 的重发请求的话,就进入 CLOSED 状态。当 B 收到确认应答后,也便进入 CLOSED 状态。
注意:
- [ ] 主动关闭的一方状态变化为:建立状态、第一次等待(
FIN-WAIT-1
)、第二次等待(FIN-WAIT-2
)、等待计时(TIME-WAIT
)、关闭 - [ ] 被动关闭的一方状态变化为:建立状态、关闭等待(
CLOSE-WAIT
)、最后确认(LAST-ACK
)、关闭状态。 - [ ] 主动关闭的一方最后有等待计时状态
MSL(MAX Segment Lifetime
):最长报文段寿命
- [ ] MSL建议设置为2分钟
等待计时器
- [ ] 等待计时器,最长等待时间2MSL
- [ ] 等待过程中,不会释放端口,只有等到等待计时器结束后,才释放
为什么需要等待2MSL
?
- [ ] 最后一个报文没有确认
- [ ] 确保发送方的
ACK
可以到达接收方(第1个作用) - [ ] 2MSL时间内没有收到,则接收方会重发
- [ ] 确保当前连接的所有报文都已经过期(第2个作用)
等待计时状态就像主动提分手的那个人等待对方确实放下了,nice person
# 7.1. 为什么建立连接是三次握手,关闭连接确是四次挥手呢?
建立连接的时候, 服务器在 LISTEN
状态下,收到建立连接请求的 SYN
报文后,把 ACK
和 SYN
放在一个报文里发送给客户端。
而关闭连接时,服务器收到对方的 FIN
报文时,仅仅表示对方不再发送数据了但是还能接收数据,而自己也未必全部数据都发送给对方了
# 8. TCP 小结
# 8.1. 为什么 TCP 这么复杂?
因为既要保证可靠性, 同时又要尽可能提高性能
# 8.2. 保证可靠性的机制
- 校验和
- 序列号(按序到达)
- 确认应答
- 超时重传
- 连接管理
- 流量控制
- 拥塞控制
# 8.3. 提高性能的机制
- 滑动窗口
- 快速重传
- 延迟应答
- 捎带应答
# 8.4. 定时器
- 超时重传定时器
- 保活定时器
- TIME_WAIT 定时器
# 8.5. TCP/UDP的区别?
TCP:
- 面向连接(TCP三次握手)
- 可靠的(每发送一个包都会等待对方确认)
- 基于字节流(缓冲区,应用层发送来的数据分段再进行发送)
UDP:
- 无连接
- 不可靠
- 面向报文(应用层发来的数据直接传出去,没有缓冲区)
# 8.6. TCP 对应的协议和 UDP 对应的协议
TCP对应的协议:
- FTP:定义了文件传输协议,使用21端口。
- Telnet:一种用于远程登陆的端口,使用23端口,用户可以以自己的身份远程连接到计算机上,可提供基于DOS模式下的通信服务。
- SMTP:邮件传送协议,用于发送邮件。服务器开放的是25号端口。
- POP3:它是和SMTP对应,POP3用于接收邮件。POP3协议所用的是110端口。
- HTTP:是从Web服务器传输超文本到本地浏览器的传送协议。
UDP对应的协议:
- DNS:用于域名解析服务,将域名地址转换为IP地址。DNS用的是53号端口。
- SNMP:简单网络管理协议,使用161号端口,是用来管理网络设备的。由于网络设备很多,无连接的服务就体现出其优势。
- TFTP(Trival File Transfer Protocal),简单文件传输协议,该协议在熟知端口69上使用UDP服务。
← Ip_protocol UDP →