小王学习录
共勉
真正的勇士,能够在认清生活的本来面目之后仍然热爱生活
前言
TCP协议是一个很复杂的协议,本篇文章有万余字
,各位看官可以根据目录跳转到自己想要的模块。
TCP协议
上篇文章中简单介绍了一下TCP协议的特点是:有连接
,可靠传输
,面向字节流
,全双工
。
TCP报文结构
先简单介绍一下报头,16位源端口号
、目的端口号
和校验和
在UDP中已经聊过,这里就不多介绍了,看其他字段:
4位首部长度
:描述TCP报文的首部长度,单位为32位,也就是说TCP首部长度最多为60个字节
。而固定长度为20字节
,所以选项字段的长度最大为40个字节选项
:选项字段用于在TCP首部中添加一些可选的信息和配置,如报文段最大长度、窗口大小因子、时间戳等。选项字段的长度是可变
的,可以根据需求包含一个或多个选项。6位保留位
:给报头保留点空间,以便于日后TCP协议升级, 添加报头字段,减小升级成本,提高可扩展性。(C语言中的保留字同理值得学习
)- 剩下的字段结合TCP核心机制进行介绍:
TCP核心机制
在TCP中有很多机制,在这里我们关注其中最核心的十个机制。通过这十个机制同时介绍一下报文结构中的字段。
1. 确认应答
确认应答机制是保证可靠传输的最核心机制
,确认应答
和超时重传
共同保证了可靠传输,这里先介绍确认应答,稍后介绍超时重传。
首先需要注意的是,可靠传输并不代表数据一定会被传输过去,而是发送者能够知道当前报文是否发送成功,这就需要借助确认应答
了
所谓确认应答
就是接收方收到发送方的报文之后会给接受方发送一个应答报文
,用于告知发送方当前报文已经收到,可以发送下一个报文。此时ACK字段
,序号
和确认序号
字段便开始发挥作用了。
ACK:
用于标识当前报文是否为应答报文,值为1时表示是应答报文,值为2则不是应答报文。
序号
:对于普通报文,用于标识此报文开始时的内容的字节序列。对于应答报文,用于标识收到的报文开始时的内容的字节序列。很显然,这两个值为同一值
确认序号
:对于普通报文,确认序号字段没有任何意义。对于应答报文,用于标识下一个字节序列号。意思是此序列号之前的数据已经收到。其值是期待下一次传输的字节序列,也就是已经接受的字节序列号+1。
以A要向B发送2000字节的数据,一次发送1000字节为例
>1. 小王在画图的时候犯了两个个错误
,第一序号并不一定会从1开始,而是在三次握手时随机生成的(三次握手下面介绍)。第二应答报文的序号和请求报文的序号实际上并不相同
。这也是小王后知后觉的,请各位看官见谅
。
2. 在建立连接时会进行三次握手
(三次握手下面介绍),在三次握手的过程中A和B会各自生成一个初始的序号
,这个序号是随机的
。各自生成序号之后再互相告知
对方自己的序号(互相认识,建立认同
)。
3. 双方的初始序号不一样是为了防止恶意方(网络攻击方)容易预测或劫持连接
,增加了连接的安全性
,因为攻击者难以预测下一个序号。此外,使用随机的序号可以防止重放攻击
,其中攻击者试图重新发送以前捕获的数据包。
我们知道一条报文从A端发送到B端有多条网络路径
,每条路径上的路由设备,交换机设备的转发速度
都不同。而先后两次报文传输的网络路径
并不一定相同,这就有可能造成先发后至
的情况,即第二次发送的应答报文先到达A端而被错认为
是第一次报文的应答报文,使用序号和确认序号
就解决了这个问题。每条普通报文的序号和此报文的应答报文的应答序号一 一对应。
综上所诉,TCP的可靠传输最主要就是通过确认应答
机制来实现的。通过应答报文,发送方就可以知道数据是否传输成功
。进一步引入序号和确认序号
,就可以对多组数据进行详细区分
2. 超时重传
在上面讨论确认应答时,我们默认每次传输都是顺利的,并没有考虑丢包的情况。
丢包有两种情况,第一是发送方发的数据丢了
,第二是应答报文丢了
(也有可能是应答报文传输太慢了),总之最后的结果就是在规定的时间阈值
内发送方没有收到应答报文(发送方发送报文之后会开始计时,到达规定的时间后没有收到应答报文则视为丢包
)。
当到达规定的时间发送方仍没有收到应答报文时,就会重新发送一次相同的数据。这就叫超时重传
,那么问题又来了,超时重发就势必有可能造成接收方收到了两组重复的数据。对于这种情况,传输层有自己的处理方式 — 去重
去重
:实际上TCP的每一个socket
对象都有一个叫做“接收缓冲区”
的空间(接收方的操作系统内核里的一块内存),当网卡收到发送过来的数据时,会把数据先写到接收缓冲区
中,在接收缓冲区
中根据报头中的序号进行排序
并判断当前数据是否与已有数据重复
,如果重复则丢弃
,这就保证了inputStream对象执行read
方法读取到的数据一定是有序且不重复
的(read方法就是从接收缓冲区中读取数据)。
需要注意的是去重
和重新为发送方发送应答报文
并不冲突。
通过上诉介绍的去重机制
和重排序机制
,只要发送方发现在规定时间内没有收到应答报文,都会重传数据。即使发生了数据重复
、序号错乱
,接收方都能很好的处理这些问题(需要注意的是去重和重排序都会用到报头中的序号字段
)。
- 当发送方迟迟没有收到应答报文时,会进行多轮的超时重传,随着轮次的增加,时间阈值(发送方等待时间)也会逐渐增加(就算着急也发不过去,就慢慢发呗)。
- 当重复多轮重传都没有收到应答报文时,认为网络发生了故障,再传也没有意义。此时TCP会尝试重置连接(断开重连),如果重置失败&#x