目录

TCP&UDP

TCP/UDP

传输层

传输层的定义

  • 传输层是第一次在端对端也就是主机对主机的一层 专门负责处理上层的数据 负责可靠不可靠的传输
  • 传输层下层是使用 mac 和 ip 地址来寻找到特定主机 但是光凭 mac ip 可不够,还要需要端口, 也是在这一层 有了端口的概念
  • 这一层的数据单位称为数据段

TCP

TCP 概念 & 流控制

  • TCP是 面向有链接 协议, 因为他是 流控制,也被称作流式协议
  • 流控制: 接收端告诉发送端 我这边可以接收多少数据 发送端也跟接收端确认少数据 取最小值 将数据切割
  • TCP是可靠协议 他有一系列的方法来实现可靠性

TCP 序列号 & 应答机制

  1. 引出:
    • TCP是一个可靠协议 所以TCP需要各种方法来保证他的可靠性
  2. 解决:
    • 发送端发送数据后 接收端接收成功 会发送一个ACK应答
    • 缺点
      • 万一ACK发送失败 发送端就会一直发送数据 这是一个问题
  3. 优化:
    • 引入 序列号 机制 为每一个数据都打上一个序列号 ACK也算一个序列号
    • 接收端收到数据后, 就会分析她下一次应该接收数据的序列号 然后以ACK应答出去

TCP 重发超时

  1. RTT 与 RTO

    • RTT 和 RTO的概念

      • TCP作为一个面向有连接型的协议,需要保证其可靠性 所以其内部实现了一个重传计时器
      • 每发送一个数据包,就给这个数据设置一个重传计时器, 如果在计时器超时之前收到了针对这个数据包的ack,就取消这个计时器。如果没有收到,则开始发起重传。计时器超时的时间被称为RTO,这个时间的确定取决于RTT
  • 关于两者详细的解释

    • RTT(Round Trip Time): 一个连接的往返时间,即数据发送时刻到接收到确认的时刻的差值
    • RTO(Retransmission Time Out): 重传超时时间,即从数据发送时刻算起,超过这个时间便执行重传
  1. RTT的测量

    • 每发送一个分组 TCP就会对其采样,这个采样只会对同一时间的数据段进行采样, 随后用这个采样记录当作RTT
    • 采样方法一般有两种
      • 采用时间戳: 发送一个数据段时在TCP选项中记录下时间 收到数据段再记录下时间 随后计算出差值 就把这个差值作为RTT 但是需要发送端和接收端都需要支持这个选项
      • 重传队列中数据包的TCP控制块: 每个数据包第一次发送出去后都会放到重传队列中,数据包中的TCP控制块包含着一个变量,tcp_skb_cb->when,记录了该数据包的第一次发送时间。如果没有时间戳选项,那么RTT就等于当前时间和when的差值
  2. RTO的计算

    • 为了避免单次RTT波动,计算RTO时新引入了变量SRTT,表示更加平滑的RTT数值,它的计算方法:
    1
    2
    
    SRTT = x(SRTT) + (1 - x)RTT;
    // x被称为平滑因子,一般建议设置在[0.8, 0.9],意思是SRTT值百分之八十来自于之前的值,百分之二十来自于当前值。
    
    • 计算RTO的方法为:
    1
    2
    
    RTO = min(ubound, max(lbound, y(SRTT)));
    // y 是时延离散因子,推荐值为[1.3, 2.0],ubound是RTO的上边界,lbound是RTO的下边界
    
  3. 算法的缺点

    • 在RTT波动较大时,RTO不能明显适应网络变化
  4. 标准方法

    1. 标准方法引入了平均偏差的概念,它类似于统计学里面的方差,但是因为方差的计算过程代价较大,对于快速TCP来说不太适合。假设rtt的值为M,RTO的计算方式为:
    1
    2
    3
    4
    5
    6
    7
    
    srtt = (1 - g)srtt + g(M);
    rttval = (1 - h)rttval + h(|M - rttval|);
    RTO = srtt + 4(rttval);
    /*    
        其中`g`设置为1/8,`h`设置为`1/4`
        对srtt而言,它有1/8取决于当前值,7/8取决于现有值    当RTT变化时,偏差增量越大,RTO的增量也越大
    */
    

TCP 三次握手

  1. 第一次握手
    • SYN = 1,seq = x
    • 客户端发送一个 SYN标志为1,指明客户端打算连接的服务器端口,以及初始的序列号为随机生成的 x 的一个TCP包
    • 发送完成后,客户端进入 SYN_SEND状态
  2. 第二次握手
    • SYN = 1,ACK = 1,seq = y,ACKNum = x+1
    • 服务端发回 SYN=1 ACK=1,并且ACK也算一个序列号+1 所以ACKNum是 x+1,随后再把自己要发送的数据标上序列号,序列号变成了 y 的一个TCP包
    • 服务端发送完毕后 进入 SYN_RECV状态
  3. 第三次握手
    • ACK = 1,ACKNum = y+1
    • 客户端再次发送确认包(ACK),SYN 标志位为0,ACK 标志位为1,并且把服务器发来 ACK 的序号字段+1,放在确定字段中发送给对方,并且在数据段放写ISN的+1
    • 发送完毕 客户端进入 ESTABLISH状态,服务端接收到这个包后 也进入ESTABLISH状态,TCP握手结束

TCP 四次挥手

  1. 第一次挥手
    • FIN = 1, seq = x
    • 假设客户端想要关闭连接,客户端发送一个FIN标志位置为1的包,表示自己像断开连接 没有数据可以发送了,但是仍然可以接收数据
    • 发送完毕后,客户端进入 FIN_WAIT_1 状态
  2. 第二次挥手
    • ACK = 1 ACKNum = x + 1
    • 服务端接受到了客户端想要断开的链接的请求,便发出了一个ACK标志位为1的TCP包,表明自己接收到了请求,但还没有准备好关闭连接
    • 发送完毕后,服务器端进入 CLOSE_WAIT 状态,客户端接收到了这个确认包之后,进入 FIN_WAIT_2的状态,等待服务端关闭连接
  3. 第三次挥手
    • FIN=1,seq=y
    • 服务器端准备好关闭连接时,向客户端发送结束连接请求,FIN 置为1
    • 发送完毕后,服务器端进入 LAST_ACK 状态,等待来自客户端的最后一个ACK
  4. 第四次挥手
    • ACK = 1,ACKNum = y + 1
    • 客户端接收到来自服务器端的关闭请求,发送一个确认包
    • 客户端发送完包并进入 TIME_WAIT 状态,等待可能出现的要求重传的ACK包
    • 服务端接收到这个确认包后,关闭连接,进入CLOSED状态

为什么需要3次握手 挥手需要4次

  1. 3次握手目的是要确定客户端和服务端通信也就是两边的“收”“发”功能是否正常
    • 第一次握手: 客户端发送网络包 服务器收到了 这个时候服务端就能确定客户端的"发" 和 服务端的 “收” 都没有问题
    • 第二次握手: 服务端发送 这个时候客户端就能确定 客户端的 “发收” 服务端的 “收发” 是没有问题的 但是服务端还没有确定
    • 第三次握手: 客户端发包 这个时候服务端就能确定 服务端的 “发收” 客户端的 “收发” 是没有的问题的
    • 所以综上所述 两次握手是没有办法确定 双方的通信能力是否正常 至少也要三次
  2. 4次挥手目的是要数据接收完毕 不能在数据没有接受完全就直接关闭了连接TCP连接是双向传输的对等的模式, 就是说双方都可以同时向对方发送或接受数据
    • 第一次挥手: 当有一方要关闭连接时,会发送指令告知对方 我们要close连接
    • 第二次挥手: 对方回一个ack应答 此时一个方向的连接关闭 但是!另一个方向仍然可以继续传输数据 等到数据发送完 就进行第三次挥手
    • 第三次挥手: 发送FIN段
    • 第四次挥手: 回ACK应答

TCP 以段为单位发送数据

  1. 什么是段
    • 在三次握手的期间发送端会告诉接受端 我一次性能发送多少数据接受端也会告诉发送端 我一次性能接受多少数据随后发送端就会把全部数据切割为最小值 发送出去
    • 这个最小值为段

TCP 窗口控制

  1. 引出
    • 当我们以段为单位 一次发送数据 随后又得等待ack 这样包的往返效率很慢
    • 所以tcp采用了滑动窗口来优化
  2. 什么是窗口控制
    • 滑动窗口就是我们设置窗口值 在没超够窗口值的前提下 不用等待ack的应答 就可以发送段数据

TCP 重发控制

  1. 引出
    • 当我们利用窗口来发送数据 如果有数据丢失怎么办
  2. ACK丢失
    • 如有几个ack应答丢失是没有关系的 因为剩下的ack会到达发送端
    • 所以一对比单个段发送的效率 窗口的性能还是蛮高的
  3. 段丢失
    • 如果段数据丢失了 接受端会一直返回相对应的序列号的ack应答 如果发送端一直接受同样的ack三次 就会进行重发

TCP 拥塞窗口

  1. 引出

    • 计算机网络都处在一个共享的环境。 因此也有可能会因为其他主机之间的通信会造成网络拥堵。如果在网络拥堵的时候 发送一个较大量的数据包 会可能导致整个网络的瘫痪
  2. 什么是拥塞窗口

    • TCP在通信一开始的时候会通过一个叫做慢启动的算法得出的数值,对发送数据量进行控制
    • 首先,为了在发送端调节要发送数据的量,定义了一个叫做 “拥塞窗口” 的概念 在慢启动的时候,将这个窗口调节为1个数据段发送数据,随后没收到一个ack就进行+=1 在发送数据的时候 也会将其拥塞窗口的大小和接受端的窗口对比 取其最小值 然后发送比这个最小值还小一点的数据
  3. 上述解决办法会出现的问题

    • 随着包的往返,拥塞窗口也会以 1 2 4 等指数函数增长,拥堵状况激增甚至导致拥塞的发生
    • 慢启动阈值他也就来了
  4. 慢启动阈值

    • 只要拥塞窗口的值超过这个范围,则每一次收到ack,只允许下面这种比例放大拥塞窗口

    • 1
      
      1个数据段的字节数 / 拥塞窗口(字节) X 1个数据段字节数
      

TCP 连接状态

  • CLOSED: 初始状态
  • LISTEN: 服务器处于监听状态
  • SYN_SEND: 客户端socket执行CONNECT连接,发送syn包 进入此状态
  • SYN_RECV: 服务端收到SYN包并发送服务端SYN包,进入此状态
  • ESTABLISH: 表示连接建立。客户端发送了最后一个ACK包后进入此状态,服务端接 收到ACK包后进入此状态
  • FIN_WAIT_1: 终止连接的一方发送了FIN报文后进入,等待对方FIN
  • CLOSE_WAIT: 假设服务器)接收到客户机FIN包之后等待关闭的阶段。在接收到 对方的FIN包之后,自然是需要立即回复ACK包的,表示已经知道断开请求。但是本 方是否立即断开连接(发送FIN包)取决于是否还有数据需要发送给客户端,若有, 则在发送FIN包之前均为此状态
  • FIN_WAIT_2: 此时是半连接状态, 既有一方要求关闭连接,等待另一方关闭,客户端接收到服务端的ACK包,但并没有接收到服务端的FIN包,进入FIN_WAIT_2状态
  • LAST_ACK: 服务端发动最后的FIN包,等待最后的客户端ACK响应,进入此状态。
  • TIME_WAIT: 客户端收到服务端的FIN包,并立即发出ACK包做最后的确认,在此之 后的2MSL时间称为TIME_WAIT状态。

TCP 首部格式

  1. 源端口号
    • 发送方的应用端口 占16位
  2. 目标端口号
    • 接受端的应用端口 占16位
  3. 序列号
    • 占32位
    • 发送端会在发送数据的每个字节上标上序号
    • 不一定每一个序列号都是0, 1开始的 这个序列号是随机的 会在syn包也就是第一次握手 告诉接受端
    • syn包 & fin包 & ACK 都是一个字节
  4. 确认应答号
    • 占32位
    • 收到数据后 会返回下一次应该收到的序列号信息作为确认应答
    • 这个确认应答也就代表着 前面的数据我都收到了的意思
  5. 偏移量
    • tcp首部长度
  6. 保留
    • 占4位 主要是为了以后扩展用的 一般都是0
  7. 控制位
    • 字段长为8位, 当它们对应位上的值为1 就会有特殊作用
    • 三次握手, 四次挥手
      • ack 该位为1时, 确认应答的字段变为有效, tcp规定除了最开始的syn包外, 必须为1
      • syn 该位为1时, 代表希望建立连接, 并且序列号会随机生成
      • fin 该位为1时, 代表希望断开连接
    • 英语全称(其实一开始作者看错了 以为都是p开头 结果阴差阳错发现了 然后就记住了 哈哈) =-=
      • psh(push) 该位为1时,代表需要直接将数据传给上一层 / 该位为0时 需要先进行缓存在进行传送
      • rst(reset) 该位为1时,代表tcp连接出现异常 必须强制断开连接 比如对方突然断电
    • 紧急指针相关
      • URG 该位为1时,代表包中有需要紧急处理的数据
    • 拥塞窗口
      • cwr 该位为1时,则会通知对方拥塞窗口缩小
      • ece 该位为1时,通知对方,从对方到这里的网络有拥塞
  8. 窗口大小
    • 长为16位
    • 代表发送数据最多不能超过这个窗口大小
    • 如果窗口大小为0 则就是代表可以窗口探测 去寻找最新的窗口大小
  9. 校验和
  10. 紧急指针
    • 该字段长为16位, 只有在URG控制位为1时有效
    • 数据的首位到紧急指针指向的位置 都是紧急数据
    • 怎么处理紧急数据 就是应用层要实现的事情, 一般在暂停通信 或者中断通信的时候使用
  11. 选项

UDP

UDP 概念 & 用途

  1. UDP 是面向无连接协议 爆式协议 他不会去管数据到底有没有到达 所以想啥时候发数据就啥时候发数据经常用于广播 视频 音频等

UDP 首部格式

  1. 因为UDP简单 所以首部只有 源端口号 目标端口号 检验和 包长度 四个数据