【网络原理2】---TCP协议的格式

TCP 协议

TCP 协议相对于 UDP 是复杂不少的。
在网络编程这里已经讲了 TCP 的特点:
有链接 可靠传输 面向字节流 全双工
可靠传输 是 TCP内部的机制,和编码关系不大,我们的感知不是很清楚。接下来在下面的解析种会了解可靠传输的实现机制。

TCP 协议段格式

在这里插入图片描述
这个图片来自于一本书《图解TCP/IP》,这本书对于网络原理来说是一本很不错的书籍。

  • 端口号: 这两个和UDP是一样的,都是表示端口号。
  • 16位校验和: 和UDP 的检验和同理
  • 保留(resevered): 类似于C语言中的保留字。这时候还没用,保不齐以后什么时候就要用了,所以你先占个位置,你别人先用别的。此处的 TCP 的保留6位,也是为了以后的扩展来考虑到。
  • 选项(option):此处的选项相当于对于这个TCP 报文的一些属性进行解释说明的。
  • 4位首部长度: 存储TCP报头的长度

为什么要有保留位?
对于网路协议来说,扩展升级,是一件成本极高的事情!!! 就说UDP,报文长度是2 个字节,因此一个包做大是 64K。那么能不能把 UDP 协议升级一下,让他支持更大的长度呢?比如说把报头长度使用4字节来表示。
理论上可行,仅仅只需要改一下UDP报文长度从2字节 变到 6字节,但是实际操作成本极高,这不是技术问题,而是营销问题。全世界上百亿台能上网的计算机/路由器/手机……。此时这些设备的操作系统里们就是支持的 2 字节长度的 UDP。要想进行升级,就得让这些设备的操作系统都能够同步升级成 4 字节的 UDP。
如果引入“保留位” 此时升级操作系统的成本会低不少。如果后续 TCP 引入了一些新的功能,就可以使用这些保留位字段。此时,对于,TCP 本来的报头结构影响是比较小的,老的设备即使不升级也很容易兼容。

咱们再开发程序的时候,其中一个重点考虑的事情就是可扩展性。有些功能可能暂时不需要,保不齐未来就需要。

为什么要有 4位首部长度 呢?
一个 TCP报头,长度是可变的,不像 UDP 一样是固定8个字节,因此首部长度就描述了 TCP 报头具体是多长。另外,UDP报头除了选项部分外的是固定长度(20 字节)。首部长度 - 20 字节 得到的就是选项部分的长度。另外,注意此处的首部长度是 4 bit。4 bit => 0 - 15。需要注意的是首部长度的单位不是字节,而是 4个字节。

  • 如果首部长度是5,表示整个 TCP 报头是20个字节(相当于没有选项)
  • 如果首部长度的值是15 ,表示整个TCP 报头的长度是 60 字节(选项相当于40个字节)

剩下的 32位序列,32 位确认序列,16位窗口大小,16位紧急指针等。 这些在接下来的讲解中一一解释。

TCP内部的工作机制

TCP 是一个复杂的协议,里面有很多机制。咱们当前主要讨论TCP 提供的 10 个 核心的 机制。

1. 确认应答

TCP 是可靠传输,确认应答工作机制是实现可靠传输的最核心机制。
可靠传输,是怎样做到可靠的???注意一下,这里的可靠传输,不是说,发送方 100% 能把消息发送给接收方……(毕竟如果网线都断了,不可能发送过去)尽力而为,尽可能把知道的数据传输过去。同时,如果传输不过去,至少能知道。

假设此处,我现在要请朋友吃饭。
在这里插入图片描述
当主机A 的主人收到 “好啊好啊” 的时候,主机A主人就知道了主机B的主人看到了发送的消息(换句话说,短信没有丢包),如果等了半天,没有收到主机B发来的消息,说明消息大概率就是没了。
TCP 进行可靠传输,最主要的就是靠这个确认应答机制。A给B发消息,B收到之后会返回一个应答报文(ACK),此时A 收到应答之后,就知道刚刚发的消息已经顺利到达B了。
生活中随处可见的这种应答机制。比如咱们打电话,大打电话就相当于可靠传输。
考虑更复杂一种的情况:我突然想到对方前两天说生病了,没胃口吃东西。
在这里插入图片描述

此处我可以连续发两条消息,不需要等第一个消息的回应(对方是看到消息是立即回应的)。
但是网络上可能存在“先发后至”。这种情况下,收到的消息的顺序是可能存在变数的。
在这里插入图片描述

由于“先发后至”,我先收到的 “NO!!” 后收到的 “好呀好呀”。
这时候我看到的意思就是对方不想吃,现在胃口不好,想等两天再吃。
这就会闹出误会了。

结论:网络先发后置的这个现象是客观存在的。无法避难的。因此应答报文到达的顺序也是可能发生变动的,此时要考虑如何规避这种顺序错乱带来的歧义。

如何解决上述这个问题呢?
办法很简单,给传输的数据和应答报文,都进行编号就可以了。

在这里插入图片描述
当我们引入序号之后,此时就不怕顺序乱了。即使顺序乱了,也可以通过序号来进行区分当前应答报文是针对哪个数据进行的。
任何一条数据(包括应答报文)都是有序号的。确认序号,则是只有应答报文有(普通报文确认序号字段里的值无意义)。

在这里插入图片描述
一条报文是否是应答报文,取决于ACK,如果这个ACK 这个标志位 为1,表示是应答报文。如果为 0 表示不是应答报文了。
应答报文的序号仅仅是一个身份标识。不需要应答报文的应答报文。
实际上 TCP 的序号并不是按照“一条两条“ 这样的方式来进行编号的。TCP 是面向字节流的,TCP 的序号也是按照字节来编号的。

假设一条数据是1000个字节
假设是从1 开始编号,此时第一个字节序号就是1,第二个字节序号就是2……
但由于这个 1000 个字节都属于同一个 TCP 报文,TCP 报头 里就只有记录当前的第一个字节的序号。此处报头写的数据是 1.
接下来如果再发送第二条数据,此时第二个数据报的 第一个字节序号 就相当于 1001,如果长度是1000 此时最后一个字节序号是 2000 .由于 1001 - 2000 都属于一个 TCP 数据报。报头里只需要填写 1001 就行了。
TCP 的字节序号是依次累加的。这个依次累加的过程对于最后一条数据来说,起始字节的序号就是上一个数据的最后一个字节的序号。每个TCP 数据报的报头填写的序号是需要写 TCP 数据的第一个字节的序号即可。
TCP 知道了头一个字节的序号。再根据TCP 报文长度,就很容易知道每个字节的序号。

确认序号的取值,是收到的数据的最后一个字节的序号 + 1.
在这里插入图片描述
第一个确认应答表示含义:

  1. < 1001 的数据都已经确认收到了。
  2. A 接下来应该从 1001 这个序号开始继续发送。(B 要向 A 索要 1001 的数据)

为哈要这么设定? 为啥确认序号不直接写作1?结合后面的机制很容易理解,后面再说。

小结:TCP 可靠传输能力,最主要就是通过确认应答机制来保证的。通过应答报文,就可以让发送方清楚的知道传输是否成功。进一步引入了序号确认序号,针对多组数据进行详细的区分。

2.超时重传

前面讨论确认应答的时候,只讨论了顺利传输的情况。那么如果是丢包了呢?
丢包涉及两种情况:

  1. 发送的数据丢了
  2. 返回的ack 丢了

在这里插入图片描述
发送方看到的结果就是没有收到ack,区分不了是那种情况。这两种情况会一事同仁,都认为是丢包了。
此时 TCP 还没有躺平,还是要尽力抢救一下的。
丢包是一个概率性事件,通常情况下,丢包的概率还是比较小的。因此重新发一下这个数据报,其实还是有很大的概率传输成功的,
因此 TCP 就引入了 重传机制。在丢包的时候,就需要重新发一次同样的数据。
TCP 直接引入了一个 时间阈值。发送方发了一个数据之后,就会等待ACK此时开始计时。如果在事件阈值之外,也没收到ACK ,不管此时的ACK 是不是在路上,还是彻底丢了,都被视为丢包了!!!这个和寒假作业一样的,没带等于没写。
超时重传 超过一段时间还没有响应,就重新传输。
设个超时时间是多少呢?
这个时间是可配置的,并且在不同系统上面的默认值都是可能存在差别的。
在这里插入图片描述

对于上图的主机B 来说,1 - 1000 就受到了 两次。这个事情细思极恐,假设你发的数据是一个支付请求呢??
TCP 对于这种重复传输的数据是有特殊处理---- 去重。TCP 存在一个“接收缓冲区” 这样的存储空间(接受方操作系统内核里面的一段内存)。每个 TCP 的socket 对象,都有一个接收缓冲区(其实也是一个发送缓冲区)。
主机B 收到了 主机A 发送的数据,其实是 B 的网卡读到了数据。然后把数据放到 B 对应的 socket 缓冲区中。(想象成一个阻塞队列。) 根据数据的序号,TCP 很容易识别 当前缓冲区里的两条数据是否只重复的。如果是重复的,则把后来的这份数据就直接丢弃了!!保证了应用程序调用read 读取到的数据,一定是不重复的。
后续应用程序使用 getInputStream,进一步使用read ,就是从缓冲区来读取的。
小结:由于去重和从新排序的机制存在,发送方只要发现ACK 没有按时送达,就会重传数据。即使重复了,即使乱序了,都没事,接收方都能很好的处理。(去重和排序都依赖于TCP报头的序号)

重新传输是否可能再一次丢包呢?
这种情况是有可能的。因此重传可能是重传了 N 次。这个 N 并非是个很大的数字。重传这个事情,当你重传几次都没有传过去,此时重传的意义就不大了。

假设一次传输丢包的概率是10% (这是一个很大的数字了)
传输成功的概率是 90%
如果来连续两次丢包概率是 1%
连续三次丢包的概率是 0.1 %
来纳许重传都丢包的概率是非常低的。如果此时出现了这总情况,只能说明,此时丢包的概率远不止10 % -----> 说明了你当前的网络出现了重大事故

重传达到一定的次数的时候,就不要再继续重传了,会认为网络出现了故障。接下来 TCP 会尝试重连(相当于断开重新连接),如果重置还是失败了,那就彻底断开连接。
具体重传几次 N ,也是可以配置的,不去研究。
重传的时候,第一次重传和第二次重传的超时间隔时间还是不同的。一般来说,重传的轮次越大,超时时间间隔就越大。超时时间变大,重传的频率降低,因为你重传的次数越多,说明你成功的概率就小了,此时你重传的太快也是白白浪费时间。

小结: 可靠传输时 TCP 最核心的部分。TCP 最核心的部分。TCP 的可靠传输就是通过 确认应答 + 超时重传 来进行体现的。其中确认应答描述的是传输顺利的情况。超时传输描述的是传输出现问题的情况。这两者相互配合,共同支撑整体的 TCP可靠性

  • 1
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值