【linux网络】传输层


传输层

在这里插入图片描述

端口号

端口的由来:
在操作系统中,不同的进程是通过进程标识符(pid)进行区分。不同的操作系统使用的pid的格式不尽相同,但在网络里我们需要采用统一的格式进行区分。因此端口号诞生了。它采用统一的格式来标识进程。

端口号的格式:TCP/IP: 16bit位的正整数

c++:uint16_t

在TCP/IP协议中, 用 “源IP”, “源端口号”, “目的IP”, “目的端口号”, “协议号” 这样一个五元组来标识一个通信。

端口的分类

服务端使用的端口号

  • 公认端口号: 里面一些端口固定绑定某些应用程序:1-1023

    应用程序HTTPSSHFTP
    端口号802221
  • 注册端口号:范围从1024到49151,这些端口号松散地绑定于一些服务,许多服务都可以使用这些端口。

  • 动态端口号:49152-65535,客户端运行时,操作系统动态绑定,通信时自动绑定,通信结束自动回收

UDP

UDP, user datagram protocol 用户数据报协议

UDP特点

  • 无连接
  • 不可靠,尽最大努力交付,因此数据可能丢失、乱序
  • 面向数据报,每次读取都是完整的报文,且发多少个数据报,就要收到多少个数据报
  • UDP没有拥塞控制,因此网络拥塞不会降低发送速率
  • UDP支持一对一,一对多,多对一和多对多通信
  • UDP首部开销小:8字节
  • UDP是全双工

UDP的缓存区

  • 发送缓存区:UDP没有真正意义的缓存区,在调用sendto后,内核会直接将数据交给IP层
  • 接受缓存区:UDP有接受缓存区,但是这个接受缓存区不会调整接受数据的顺序,即不保证收到的UDP报的顺序和发送UDP报的顺序一致。如果缓冲区满了, 再到达的UDP数据就会被丢弃,而且也不会通知你。

UDP格式

  • 源端口号(选用):在需要对方回信时选用,不需要则全0
  • 目的端口号:终点交付报文时必用
  • 长度:整个报文长度(大小), 最小为8字节
  • 校验:检查报文传输中是否损坏

在这里插入图片描述
如果我们需要传输的数据超过64K, 2^16bit, 则需要手动拆解数据。

UDP的应用场景

  • NFS: 网络文件系统

  • TFTP: 简单文件传输协议

  • DHCP: 动态主机配置协议

  • BOOTP: 启动协议(用于无盘设备启动)

  • DNS: 域名解析协议

  • 直播,视频

TCP

TCP的特点

  • 基于连接
  • 可靠交付(无差错,不丢失,不重复)
  • 面向字节流
  • 全双工
  • 一对一通信

TCP的格式

在这里插入图片描述

  • 源/目的端口号: 表示数据是从哪个进程来, 到哪个进程去;

  • 32位序号/32位确认号: 保障有序性

  • 4位TCP报头长度: 表示该TCP头部有多少个32位bit(有多少个4字节); 所以TCP头部最大长度是15 * 4 = 60 字节

  • 6位标志位:TCP报文是有类型的,比如一个TCP报文可能是通信报文,也可以是建立连接的报文,也可以是关闭连接的报文,因此需要用标志来区分。

​ URG: 紧急指针是否有效

​ ACK: 确认号是否有效,当该报文是应答类型的报文,该标志置1

​ PSH: 提示接收端应用程序立刻从TCP缓冲区把数据读走

​ RST: 对方要求重新建立连接; 我们把携带RST标识的称为复位报文段

​ SYN: 请求建立连接; 我们把携带SYN标识的称为同步报文段

​ FIN: 通知对方, 本端要关闭了 , 我们称携带FIN标识的为结束报文段

  • 16位窗口大小: 16位窗口大小最大为2^16-1 = 65532 字节
  • 16位校验和: 发送端填充, CRC校验. 接收端校验不通过, 则认为数据有问题. 此处的检验和不光包含TCP首部, 也包含TCP数据部分.
  • 16位紧急指针: 标识哪部分数据是紧急数据。只有当URG标志为1,才有效。紧急指针的本质是紧急数据在TCP报文里的偏移量。
  • 40字节头部选项: 暂时忽略;

与TCP相关的协议

ARQ协议

ARQ(Automatic Repeat Quest,自动重传请求)和TCP(Transmission Control Protocol,传输控制协议)在计算机网络中具有密切的关系。ARQ是一种可靠的数据传输机制,而TCP则是实现这种可靠性的一种具体协议。

常见的ARQ有三种:

  1. 停止等待(Stop-and-Wait ARQ):发送方发送一个数据包后,停止发送新的数据包,等待接收方的确认(ACK)。如果接收到ACK,则发送下一个数据包;如果在超时时间内没有收到ACK,则重传当前数据包。

    体现在TCP中:序列号和确认号,超时重传机制

  2. 回退N(Go-Back-N ARQ):发送方可以连续发送多个数据包(最多N个),但如果遇到一个数据包出错或丢失,从这个出错的包开始,所有后续的数据包都要重传。

  3. 选择性重传(Selective Repeat ARQ):发送方可以连续发送多个数据包,接收方对每个正确接收的数据包发送ACK,发送方只重传那些没有收到ACK的数据包。

    体现在TCP中:快重传

滑动窗口协议

TCP机制

可靠性原理:

  • 校验和

  • 序列号(按序到达)

  • 确认应答

  • 超时重发

  • 连接管理

  • 流量控制

  • 拥塞控制

提高性能机制:

  • 滑动窗口

  • 快速重传

  • 延迟应答

  • 捎带应答

确认应答(ACK)机制

要想确定一个报文是否有效,需要对方做出应答。但应答的有效性无法验证(验证应答的有效性会陷入循环),因此我们规定不用对 应答 做出 应答。对方发出应答就默认我收到了应答。

捎带应答:多数情况下,单纯发出应答效率不高,而且根据规定,对方发出应答就默认我收到了应答。因此为了提高效率,对方发出的报文 = 应答 + 数据。

在这里插入图片描述

序列号

TCP通信时,并不是发一个,应答一个。这样效率低下。而是一次发多个数据,发送多个数据存在乱序问题,而乱序是不可靠的一种。

TCP保证有序是通过序列号来实现(TCP报文里的32位序号)。每个报文都带有序号,对方收到多个报文,会根据序号进行排序。如何理解这个序号?

  • TCP是面向字节流的,因此我们可以抽象的认为TCP的缓存区是一个 char类型的数组,数组的元素天然带有一个编号(数组下标)

  • TCP 报文头中的 32 位序号字段用于标识 TCP 连接中每个数据包的顺序。**这个序号表示了数据包中的第一个字节在整个数据流中的位置。**序号的增长是根据发送的数据量而定的,每发送一个字节,序号就增加一个。这样,接收端就可以根据序号来确定接收到的数据包的顺序,并进行重组。

  1. 如果发送方发送了第一个TCP段,包含100字节数据,且这个TCP段的序列号为1000。
  2. 接下来发送第二个TCP段时,它的序列号将是1100(1000 + 100),因为第一个段包含了100个字节。

确认号

接受方收到一个序列号为N报文后,需要应答。该应答需要告诉对方,自己接受到了序号为N,因此要返回一个序号为M确认序号,**规定:确认序号 = 最后一个已成功接收的数据字节的序列号 + 1, 即 M = N+1 **。通知发送方可以从M处开始发数据了。

当发送方收到序号为M的应答后,规定:发送方可以认为小于序号M的所有报文,接受方全部收到。这样,我们可以允许少量应答丢失。
在这里插入图片描述

问题:那为什么一个报文同时带有确认号和序列号?
答:确认号 – 应答, 序列号 – 数据,由于存在捎带应答的情况,一个报文即是应答又是数据,因此需要同时带上确认号和序列号。

连接管理机制

TCP建立连接,需要进行3次握手和4次挥手
在这里插入图片描述
问题:三次握手的目的是什么?
答:确认双方的通信能力和可达性同步双方的序列号

​ 第一次:客户端发送报文给服务器,服务器接受到报文:服务器知道客户端发送能力正常

​ 第二次:服务器做出应答,客户端接受到报文:客户端知道服务器的接受发送能力正常

​ 第三次:客户端做出应答,服务器接受到报文:服务器知道客户端的接受能力正常

问题:为什么是三次?两次或一次不行吗?
答:先说一次,如果一次握手可以,那表示一个客户端发送一个SYN报文就可以建立,这就导致服务器很容易受到SYN洪水的攻击(即客户端发送多个SYN报文)。
再说两次,两次握手的问题和一次握手的问题类似,在两次握手情况下,服务器在做出应答后,就要开始建立连接(变为establish状态),但客户端不一定收到应答,即服务器先进入estabushed,这就存在服务器空挂连接的问题,也就是说先让服务器做出资源让步。而服务器是1对多,如果失败的情况都让服务器端着,一但服务器撑不住了,那影响的是多个客户端。
而三次握手,客户端先于服务器进入estabushed状态,如果最后一个应答丢失,也就影响一个客户端。
因此我们可以得出验证全双工的最少次数为3次。

问题:为什么要4次挥手,第二次挥手和第三次挥手为什么不能采用捎带应答的方式合成一次?
答:TCP支持连接的半关闭状态,即一端关闭发送而保持接收。当接受方收到FIN时,它可能还有数据未发送完,因此它先要发送ACK,然后等数据发送完后,再发送FIN。

流量控制

接收端处理数据的速度是有限的. 如果发送端发的太快, 导致接收端的缓冲区被打满, 这个时候如果发送端继续发送,就会造成丢包, 继而引起丢包重传等等一系列连锁反应. 因此TCP支持根据接收端的处理能力, 来决定发送端的发送速度. 这个机制就叫做流量控制(Flow Control);

流量控制是通过接收端抑制发送端发送数据的速率,以使接收端来得及接收。是点对点通信量的控制,是个端到端的问题。

流量控制的手段:滑动窗口
在这里插入图片描述

  • 接收端将自己可以接收的缓冲区大小放入 TCP 首部中的 “窗口大小” 字段, 通过ACK端通知发送端;

  • 窗口大小字段越大, 说明网络的吞吐量越高;

  • 接收端一旦发现自己的缓冲区快满了, 就会将窗口大小设置成一个更小的值通知给发送端;

  • 发送端接受到这个窗口之后, 就会减慢自己的发送速度;

  • 如果接收端缓冲区满了, 就会将窗口置为0; 这时发送方不再发送数据, 但是需要定期发送一个窗口探测数据段, 使接收端把窗口大小告诉发送端.

滑动窗口

刚才我们讨论了确认应答策略, 对每一个发送的数据段, 都要给一个ACK确认应答. 收到ACK后再发送下一个数据段.

这样做有一个比较大的缺点, 就是性能较差. 尤其是数据往返的时间较长的时候。因此为了提高效率,我们需要一次发送多段报文,而TCP使用滑动窗口来管理多段数据的发送。

窗口越大, 网络吞吐量就越大, 传输效率就越高.

问题:滑动窗口在哪里?发送缓存区的一部分

滑动窗口将发送缓存区分为了3部分:

在这里插入图片描述
在这里插入图片描述
滑动窗口如何解决丢包问题?

  1. ACK丢了
    在这里插入图片描述
    根据确认序号的定义:该序号之前的数据已经全部接受。
    因此少量的丢包不会影响。

  2. 数据包丢了
    在这里插入图片描述
    现在:发送方:1000 2000 3000 4000 其中2000丢了 接受方没有接受到2000,但接受到了3000 4000,但根据确认号的定义,接受方只能发送ACK = 1001,当发送方接受到3个相同的ACK,会触发快重传机制,重发数据包

拥塞控制

虽然TCP有了滑动窗口这个大杀器, 能够高效可靠的发送大量的数据. 但是如果在刚开始阶段就发送大量的数据, 仍然可能引发问题. 因为网络上有很多的计算机, 可能当前的网络状态就已经比较拥堵. 在不清楚当前网络状态下, 贸然发送大量的数据,是很有可能引起雪上加霜的. 因此TCP引入了拥塞控制

拥塞控制的目的是防止过多的数据注入到网络中,避免网络中的路由器或链路过载。是一个全局性的过程,涉及到所有的主机、路由器,以及与降低网络传输性能有关的所有因素。
在这里插入图片描述

TCP 进行拥塞控制的算法有四种

  • 慢开始(slow-start)
  • 拥塞避免(congestion avoidance)
  • 快重传(fast retransmit)
  • 快恢复(fast recovery)

此外引入2个概念:拥塞窗口(cwnd:congestion window)和慢开始门限 (ssthresh)

拥塞窗口:初始为1,根据拥塞控制算法进行修改,它的作用:16位窗口大小 = min(cwnd, rwnd)

慢开始门限:为了防止拥塞窗口 cwnd 增长过大引起网络拥塞,还需要设置一个慢开始门限。具体来说,它用来控制什么情况下执行哪一种拥塞控制算法。

算法思想如下:cwnd 初始置1

  1. 刚开始执行慢开始算法,cwnd成指数增长

  2. 当cwnd > ssthresh,执行拥塞避免算法(特殊情况:cwnd == ssthresh,执行慢开始、拥塞避免都可以),开始进行线性增长

  3. 当出现下面2种情况:

    • 情况1:超时,发送方长时间未收到接受方的ACK,判定为网络拥塞。则cwnd置1,ssthresh变为超时时的cwnd的一半。进入慢开始阶段
      在这里插入图片描述
    • 情况2:快重传,发送方收到接受方3个相同的ACK。则cwnd == ssthresh == 快重传时cwnd的一半,进入快恢复阶段
      在这里插入图片描述

粘包问题

首先要明确,粘包问题中的"包”,是指的应用层的数据包.
在TCP的协议头中,没有如同UDP一样的“报文长度”这样的字段,但是有一个序号这样的字段。
站在传输层的角度,TCP是一个一个报文过来的.按照序号排好序放在缓冲区中.
站在应用层的角度,看到的只是一串连续的字节数据.
那么应用程序看到了这么一连串的字节数据,就不知道从哪个部分开始到哪个部分,是一个完整的应用层数据包?

那么如何避免粘包问题呢? 归根结底就是一句话,明确两个包之间的边界

  • 定长报文:对于定长的包,保证每次都按固定大小读取即可; 例如上面的Request结构,是固定大小的,那么就从缓冲区从头开始按sizeof(Request)依次读取即可;

  • 特殊字符分割:对于变长的包,还可以在包和包之间使用明确的分隔符(应用层协议,是程序猿自己来定的,只要保证分隔
    符不和正文冲突即可);

  • 自描述字段:带上报文属性,如http的状态行和请求头

思考: 对于UDP协议来说,是否也存在“粘包问题”呢?
答:对于UDP 如果还没有上层交付数据,UDP的报文长度仍然在.同时,UDP是一个一个把数据交付给应用层.就有很明确的数据边界站在应用层的站在应用层的角度,使用UDP的时候,要么收到完整的UDP报文,要么不收.不会出现"半个"的情况.

TCP异常情况分析

  1. 进程终止:文件的生命周期随进程,当进制终止时,os会自动进行4次挥手
  2. 机器重启:同上,关机时,os会先终止所有进程
  3. 网线断了、断电: TCP选项里有保活定时器,如果客户端长时间不发消息,服务器会自动释放连接
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值