IT数码 购物 网址 头条 软件 日历 阅读 图书馆
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
图片批量下载器
↓批量下载图片,美女图库↓
图片自动播放器
↓图片自动播放器↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁
 
   -> 网络协议 -> 计算机网络模型(三):运输层 -> 正文阅读

[网络协议]计算机网络模型(三):运输层

计算机网络模型(二):应用层

简介

运输层其实很简单,就两个协议需要我们特别关心,一个是TCP协议,几乎所有的应用层协议都是基于TCP协议的;另一个就是UDP协议,也很重要。一般二者用在不同的场合。

想一下,两台网络主机要想通信,应该怎么办?

运输层提供了解决方法:

  • TCP:建立虚拟链路,消息从这个链路传过去。
  • UDP:构造一个消息包,里面有目的地,每个主机看到这个包就传给下一个离目的主机更近的主机,直到最终主机收到。

TCP

TCP协议就好比火车,乘客就是要传递的信息。火车从上海到北京,路线固定,你不会中途走错路。但是呢,至于火车应该怎么走,那就是很复杂的问题了。

TCP报文格式

请添加图片描述
简单分析一下报文,下面的序号是按行号来的:

  1. 源端口:占16位,2字节,定义了TCP报文(考点,一会说)是从哪个端口传来的。记住是端口不是地址。目的端口:占16位,2字节。
  2. 序号:占32位,4字节,是TCP滑动窗口(考点,一会说)的基础。
  3. 确认号:占32位,4字节,是可靠性保障的基础(考点,一会说)。
  4. 这个比较多,我分条:
    1. 数据偏移:占4位,是指真正的数据到报文头部的距离。但是,4位最多能标识16个数字,而TCP报文头是以4个字节长度为单位的(看图最上部单位),因此16*4=64字节。这就规范了TCP报文头部最多为64字节;
    2. 保留位:目前置0,待日后使用;
    3. URG:紧急报文(说实话我没用过也没见用过);
    4. ACK:确认ACK,只有ACK=1才有效,ACK=0的报文段丢弃;
    5. PSH:推送,该字段置1以后,不经过缓存直接交付(否则为了效率会用缓存先接收);
    6. RST:重置位,当TCP连接出现严重差错,如主机崩溃,会置1,强制断开连接。
    7. SYN:SYN=1,就说明这是申请连接或者接受连接的报文。
    8. FIN:FIN=1,说明发送方数据已经发送完毕,要求释放连接。
    9. 窗口:16位,2字节。告诉发送方,接收方最多能一次性接受多少数据量(一会说)
  5. 校验和:就是通过对首部与正文进行校验判断报文是否被篡改;紧急指针:仅在URG=1的时候有效,指明了紧急数据在报文的位置,之后都是普通报文。
  6. 选项:这部分就是可填充数据,但是全部报文头部不能超过64字节。

TCP三次握手

见文章:洪水攻击与防治方法

三次握手之后,就要传递数据了。

但是,我们之前提到,TCP连接是虚拟的,所以一定会有信息干扰的情况,在这种情况下,我们怎么处理信息从而达到可靠交付呢?

TCP可靠交付

啥叫理想可靠交付?一般我们认为满足两点要求:

  1. 传输方传输什么数据,接收方接收的数据就应该是什么。
  2. 在双方可以承受的范围内,尽可能多的传输数据。

于是,我们就出现了为了TCP协议而定制的配套协议,帮助实现TCP可靠传输。

停止等待协议/自动重传请求(ARQ)

在这里插入图片描述
我们看,当A向B传送数据,但是迟迟没有得到响应的时候,A就会重新传递数据。但是这样信道利用率极低。要是遇到网络不太好的情况,就需要一直等待。

还有一种情况吧,就是A向B发送了数据,B收到了但是回应的消息丢失了,这时候触发超时重传机制,后面都是正常的,直到某一时刻,又收到了之前丢失的确认消息,这时候我们会采取丢弃消息的方式,迟到或者确认丢失了的消息都不要了,毕竟之前已经弥补了消息的传递。

要是想提高利用率怎么办?就引出了新的消息协议:连续ARQ协议。

连续ARQ协议

发送方不管接收方有没有收到信息,都会不断向接收方传递消息,直到发现接收方传来了与预期不符的消息。我们先看看什么是连续ARQ:
在这里插入图片描述
这里它做了几件事情:

  1. 对要发送的信息进行分组,比如5个为一组,而接收方不必每个信息都回复,而是以一组为单位回复。
  2. 根据1,如果一组没有收到,或者这一组哪怕有一条消息没有收到,那么该组以及后续的组就需要重传

那我们是不是也可以对分组进行再分组?可以的。

对分组进行分组后的确认被称为累计确认。对连续到达的最后一个分组进行确认,我们就可以认为收到了之前全部的数据。

这么做的缺点是什么呢?假设我收到了1245分组的消息,但是根据协议,我会回复2的ACK,但是45已经传出去了,作废,重新传345。这叫Go-Back-N,一旦出现网络不佳的情况,这样的协议也会非常耗时。

滑动窗口

之前几个小章节说了TCP可靠交付的第一点,就是主机A发送什么数据,主机B就应该接收什么数据。那么第二点,在许可范围内尽可能多的传输数据,这个靠什么实现呢?

本章节的滑动窗口是重点,也是基础。

如果你了解计算机图形学,就会对滑动窗口有所了解。现假设我们的滑动窗口是以字节为单位的,并且滑动窗口的大小为5:
在这里插入图片描述
那么这个滑动窗口大小是怎么确定的?

滑动窗口 = MIN { 接收窗口值,拥塞窗口值 },什么是拥塞窗口值,以后说。

我们还有一点需要说明,那就是万一出错了,滑动窗口怎么处理这些错误?这就需要我们重新看一下这个滑动窗口,简化一下:

在这里插入图片描述
现在,假设25没有按序收到,也就是说24没有收到,那么B会向A发送ack=24,以求从24号开始接收,那么指针会指到P1的位置重新发送。因此,在滑动窗口内,我们还需要3个指针:P1, P2, P3

  • P3-P1:A的发送窗口(又称为通知窗口)
  • P2-P1:已发送但尚未收到确认的字节数
  • P3-P2:允许发送但尚未发送的字节数(又称为可用窗口或有效窗口)

如果主机A收到的确认帧中标识发送窗口的大小需要变小,那么发送窗口前沿不会移动,后沿会根据收到的确认帧前移,直到匹配需求大小。

超时重传时间太麻烦了,希望以后有精力在更新。

拥塞控制

我们之前提到发送窗口的确定是和网络拥塞程度有关系的,那么网络拥塞程度怎么判断?

慢开始与拥塞避免

在最开始的时候,我们把拥塞窗口大小设置为1,然后每经过1个传输轮次,也就是一个消息往返时间,拥塞窗口加倍。

假设拥塞窗口(cwnd)最初为1,那么经过5轮传输,理论上cwnd=16。

但是,假设网络中允许的最大流量为1025,那么经过多次传输轮次后,cwnd会到达1024,再次加倍就是2048,明显大于1025,于是消息阻塞了,这时候我们还需要定义一个数据,就是慢开始门限ssthresh。

我们现在把数据缩小,假设ssthresh=16,那么当cwnd=16的时候,就会改用拥塞避免算法。拥塞避免算法是,cwnd不再加倍,而是加一。

假设我们把ssthresh设置成一个非典型值,就是不是2的指数,设为24
。当cwnd到达16的时候还未到24,加倍后32超过24,开始执行拥塞避免算法:33,34,…

直到38的时候,发现传送超时了,那么ssthresh就会更新为38 的一半,即19。此时cwnd重新设置为1,开始慢开始算法进行消息传送。

快重传和快恢复

快恢复指的是当发送方发送了一套报文,现在假设报文号是1,2,3,4,5,6,7,8。

假设报文3未收到,那么接收方会重复确认收到报文2,重复三次,这样发送方会认为报文3未发出,重复发送报文3。

在这里插入图片描述
快恢复其实和拥塞避免算法很像。只不过拥塞避免算法是让cwnd从1开始倍数上涨,到达ssthresh的时候在进行累加上涨。快恢复是cwnd直接控制到ssthresh,再进行累加。

TCP四次挥手

与三次握手对应,TCP释放连接的时候也需要四次挥手作为结尾。

在这里插入图片描述
其所经历的过程为:

  1. 主机A向主机B 发送断开连接申请,此时FIN位置1,规定FIN=1时不能携带数据,但是需要消耗一个报文段。此时主机1进入半关闭状态1,等待B的确认。
  2. 主机B收到请求中断信息,向A发送确认信息。除了ACK以外,值得说明的是seq=v,此时的seq不是随机生成的,而是上一个携带数据的报文号+1的结果。然后将状态置为关闭等待状态。
  3. 此时A无数据发送,但是仍然可以接收数据。也就是说,从A到B方向的连接被释放,B到A方向的连接仍在。A收到B的确认信息后,进入终止等待状态2.
  4. 当B仍有数据要发送,就会继续发送。直到没有数据发送的时候,发送断开连接的信息,FIN=1。此时的seq=w,是上一次发送数据的seq+1。若上一次便是对A断开的确认,那么w=v+1。B进入最终等待状态。
  5. A收到B的断开申请,会回复请求,此时ACK=1,确认号ack=w+1。自己的序号是seq=u+1,因为最开始A向B发送FIN=1 的申请信息中,是要消耗一个序号的。然后A到等待状态,等待时长是两个报文最大的生存时间(2MSL),之后关闭,而B收到信息后直接关闭。

MSL

最长报文寿命(Maximum Segment Lifetime):RFC793建议为2分钟,但是工程上认为2分钟太长了,也就是说可能经过4分钟才能从time-wait等待状态真正关闭。因此工程上会缩短该时间。

==真正的关闭是在A撤销了程序控制块TCB的时候。==也就是Time-wait后,A会撤销程序控制块。

那为什么要等待两个MSL时间呢?

保证最后的ACK报文能够到达B。该报文可能会丢失,导致B无法收到FIN+ACK报文段的确认,此时B会超时重传该信息。超时重传后的时间在2MSL之内。如果不设置该时间,B可能无法对该信息进行确认,从而无法正常关闭连接。

保活计时器

服务端不会维持一个一直没有数据往来的客户端,加入保活计时器来计时。

假设2小时没有数据往来,服务器就会每75分钟构造一个探测报文,如果连续10次叹词报文无响应,主动断开连接。

UDP

UDP与TCP不同,TCP是虚拟链路,而UDP是没有链路的,那UDP是怎么向指定主机传送信息的呢?

UDP报文格式

UDP报文不像TCP那样复杂。

在这里插入图片描述
我们看到,有一个东西叫做伪首部,为什么是伪首部呢?

因为伪首部并不是真正的UDP报文,而是临时添加上去,仅仅是为了计算校验和用的部分。该部分临时添加,因此不会向下传递,也不会向上递交。也就是说,UDP报文的伪首部只在发送到接收的区间添加,而解析过程不考虑伪首部,会直接放弃该字段。至于如何检验校验和,我们一会单独说。

现在说说其他的部分:

  1. 源端口:需要对方回信的时候选用,不需要是可全部置0
  2. 目的端口:终点交付时必须用到
  3. 长度:UDP数据报的长度,最小为8,即不带数据,最大为 2 16 = 64 K B 2^{16}=64KB 216=64KB
    4.校验和:检测UDP传输中是否有错,有错则丢弃。

UDP特征

  1. 无连接
  2. 尽最大努力交付,不保证可靠
  3. 面向报文
  4. 无拥塞控制
  5. UDP支持一对一,一对多,多对一,多对多的通信。
  6. 首部开销很小,只有8字节,TCP是至少20字节。

UDP数据检验

发送方:

  1. 将全0放入校验和字段
  2. 将伪首部和数据部分视为多个16位的字串连接起来
  3. 若UDP的用户数据部分不是偶数个字节,需要填入一个全零字节,次字节不发送。
  4. 按二进制反码计算出16位字的和
  5. 将此和的二进制反码写入检验和字段,发送UDP数据报。

接收方:
6. 收到的数据(连同伪首部),按二进制反码求这些16位字的和
7. 无差错时结果应该全唯一 ,有差错则丢弃


运输层的东西就大致是这个样子了,下一篇文章更新网络层。

  网络协议 最新文章
使用Easyswoole 搭建简单的Websoket服务
常见的数据通信方式有哪些?
Openssl 1024bit RSA算法---公私钥获取和处
HTTPS协议的密钥交换流程
《小白WEB安全入门》03. 漏洞篇
HttpRunner4.x 安装与使用
2021-07-04
手写RPC学习笔记
K8S高可用版本部署
mySQL计算IP地址范围
上一篇文章      下一篇文章      查看所有文章
加:2021-07-28 08:11:23  更:2021-07-28 08:12:40 
 
开发: C++知识库 Java知识库 JavaScript Python PHP知识库 人工智能 区块链 大数据 移动开发 嵌入式 开发工具 数据结构与算法 开发测试 游戏开发 网络协议 系统运维
教程: HTML教程 CSS教程 JavaScript教程 Go语言教程 JQuery教程 VUE教程 VUE3教程 Bootstrap教程 SQL数据库教程 C语言教程 C++教程 Java教程 Python教程 Python3教程 C#教程
数码: 电脑 笔记本 显卡 显示器 固态硬盘 硬盘 耳机 手机 iphone vivo oppo 小米 华为 单反 装机 图拉丁

360图书馆 购物 三丰科技 阅读网 日历 万年历 2024年11日历 -2024/11/25 18:29:35-

图片自动播放器
↓图片自动播放器↓
TxT小说阅读器
↓语音阅读,小说下载,古典文学↓
一键清除垃圾
↓轻轻一点,清除系统垃圾↓
图片批量下载器
↓批量下载图片,美女图库↓
  网站联系: qq:121756557 email:121756557@qq.com  IT数码