传输层

作者: freemanIT | 来源:发表于2022-03-21 18:17 被阅读0次

    传输层(Transport)

    • TCP(Transmission control Protocol), 传输控制协议
    • UDP(User Datagram Protocol), 用户数据包协议
    tcp,udp比较

    UDP (数据格式检验和)

    UDP是无连接的, 减少了建立和释放连接的开销

    UDP 尽最大能力交付, 不保证可靠交付, 因此不需要维护一些复杂的参数, 首部只有8 个字节. TCP 的首部至少20 个字节

    udp格式

    UDP 长度(Length), 16 位, 首部长度+数据长度

    检验和(Checksum)

    检验和的计算内容: 伪首部+首部+数据

    • 伪首部, 尽在计算检验和时起作用, 并不会传递给网络层
    伪首部格式

    端口(Port)

    默认端口

    UDP 首部中端口占用2 个字节, 范围是0~65535

    客户端的源端口是临时开启的随机端口

    防火墙可以设置开启或关闭某些随机端口, 提高安全性

    常用命令如下

    • netstat -an, 查看被占用的端口
    • netstat -anb, 查看被占用的端口, 占用端口的应用程序
    • tlenet 主机 端口, 查看是否可以访问主机的某个端口

    TCP

    要点:

    • 可靠传输
    • 流量控制
    • 拥塞控制
    • 连接管理(建立释放连接)
    tcp首部

    TCP 数据偏移, 保留

    数据偏移

    • 占4 位, 范围0b0101 ~ 0b1111
    • 数据偏移 * 4 = 首部长度(Header Length)
    • 首部长度, 20~60 字节

    保留

    • 占6 位, 默认全为0
    保留位

    UDP 首部中哟16 位的字段记录整个UDP 报文段的长度(首部 + 数据)

    但是, TCP 首部中仅仅有个4 位的字段记录了TCP 报文段的首部长度, 并没有字段记录TCP 报文段的数据长度

    • UDP 首部中占16 位的长度字段是冗余的, 纯粹是为了保证首部是32 位对齐

    • TCP/UDP 数据长度, 完全可以由IP 数据包的首部对策出来

      传输层的数据长度 = 网络层总长度 - 网络层的首部长度 - 传输层的首部长度

    TCP 检验和(CheckSum)

    跟UDP 一样, TCP检验和的计算内容: 伪首部 + 首部 + 数据

    伪首部: 占12 字节, 尽在计算检验和时起作用, 并不会传递给网络层

    tcp伪首部检验和

    TCP 标志位

    URG(Urgent)

    • 当URG = 1, 紧急指针字段才有效, 表明当前报文段中有紧急数据, 应优先尽快传送

    ACK(Acknowledgement)

    • ACK = 1, 确认号字段才有效

    PSH(Push)

    RST(Reset)

    • RST = 1, 连接中出现严重差错, 必须释放连接, 然后再重新建立连接

    SYN(Synchronization)

    • SYN = 1, ACK = 0, 表明是一个建立连接的请求
    • 若对方同意建立连接, 则回复SYN = 1, ACK = 1.

    FIN(Finish)

    • FIN = 1, 数据已经发送完毕, 要求释放连接

    TCP 序号, 确认号, 窗口

    序号(Sequence Number)

    • 占4 个字节
    • 在传输过程中, 每一个字节都有一个编号
    • 建立连接后, 序号代表, 这一次传给对方的TCP 数据部分的第一个字节的编号

    确认号(Acknowledgement Number)

    • 占4 字节
    • 建立连接后, 确认号代表, 期待对方下一次传过来的TCP 数据部分的第一个字节编号

    窗口(Window)

    • 占2 字节
    • 这个字段有流量控制的功能, 用以告知对方下一次允许发送的数据大小(单位字节)

    TCP 可靠传输

    可靠传输是为了保证包的完整性, 当有丢包, 收到三次重复确认等情况, 就会重新发包

    TCP 可靠传输 - 停止等待ARQ协议

    ARQ(Automatic Repeat-reQuest), 自动重传请求

    arq协议 ARQ协议1

    重传次数

    若有包, 重传多次还是事变, 会一直重传到成功为止吗?

    取决于系统设置, 比如重传5 次还是失败, 就会方发送reset报文(RST)断开TCP 连接

    重传次数

    TCP 可靠传输 - 连续ARQ协议+滑动窗口协议

    连续窗口协议

    如果接收窗口最多能接收4 个包, 但发送只发了2 个包, 接收方如何确认后面还有无2个包?

    • 等待一定时间后没有第3 个包, 就会返回确认收到2 个包给发送方
    数据分割

    现在假设每一个组数据是100 字节, 代表一个数据段的数据, 每一个组给一个编号

    数据传输过程分析

    TCP 可靠传输 - SACK(选择性确定)

    在TCP 通信过程中, 如果发送序列中间某个数据包丢失. 如1, 2, 3, 4, 5, 丢失3

    TCP 会通过重传最后确认的分组手续的分组. 最后确认为2, 重传3, 4, 5

    这样原先已经正确传输的分组也可能重复发送, 降低了TCP 性能

    为改善上述情况, 发展处SACK(Selective acknowledgement) 选择性确认技术

    • 告诉对方哪些数据丢失, 哪些数据已经提前收到
    • 使TCP 只重新发送丢失的包, 不用发送后续所有的分组
    sack格式

    SACK 信息会凡在TCP 首部的选项部分

    • Kind, 占1 字节, 值为5代表这是SACK 选项
    • Length, 占1 字节, 标识SACK 选项一共占用多少字节
    • Left Edge, 占4 字节, 左边界
    • Right Edge, 占4 字节, 右边界
    sack演示

    一对边界信息需要占用8 字节, 由于TCP 首部的选项部分最多40 字节, 所以

    • SACK选项最多携带4 组边界信息
    • SACK选最大占用字节, 4*8+2 = 34字节

    为什么在传输层将数据分割, 而不是在网络层分割传递给数据链路层?

    • 因为要提高重传的性能

    • 可靠传输实在传输层进行控制的

      如果在传输层不分段, 数据一旦丢失, 整个传输层数据都得重传

      传输层分段后, 一旦部分数据丢失, 只需要重传丢失的那些段即可

    TCP 流量控制

    流量控制是点对点, 端对端, 两台设备之间的

    如果接收方缓存区满了, 发送方还是疯狂发送数据

    • 接收方智能把收到的数据包丢掉, 大量的丢包, 浪费网络资源

    流量控制:

    • 让发送方的发送速率不要太快, 让接收方及时处理数据

    原理:

    • 通过确认报文中的窗口字段来控制发送方的发送速率
    • 发送方的发送窗口大小不能超过接收方的窗口大小
    • 发送方收到接收窗口大小为0 时, 发送方就会停止发送数据

    rwind(receive window), 接收窗口

    流量控制

    TCP 流量控制 - 特殊情况

    特殊情况:

    • 一开始, 接收方给发送方发送0 窗口的报文段
    • 后面, 接收方又有了一些存储空间, 给发送方发送的非0 窗口报文段丢失
    • 发送方的发送窗口一直为0, 双方等待

    解决:

    • 当发送方收到0 窗口通知时, 这时发送方停止发送报文
    • 同时开启定时器, 隔一段时间发送测试报文询问接收方最新的窗口大小
    • 如还是0, 则发送方再次刷新启动定时器

    TCP 拥塞控制

    拥塞控制

    拥塞控制

    • 防止过多的数据注入到网络中
    • 避免网络中的路由器或链路过载

    拥塞控制是一个全局的过程

    • 涉及到所有的主机, 路由器
    • 以及与降低网络传输性能有关的所有因素

    TCP 拥塞控制方法

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

    概念:

    • MSS(Maximum Segment Size), 每个段最大的数据部分大小(建立时确定), 一般是MTU(1500) - 20 - 20 = 1460
    • cwnd(congestion window), 拥塞窗口
    • rwnd(receive window), 接收窗口
    • swnd(send window), 发送窗口. swnd = min(cwnd, rwnd)

    TCP 拥塞控制 - 慢开始

    cwnd的初始值比较小, 随着数据包被接收方确认(收到一个ACK), cwnd 就成倍增长(指数级)

    拥塞控制慢开始 cwnd慢开始

    TCP 拥塞控制 - 拥塞避免

    拥塞避免

    ssthresh(slow start threshold), 慢开始阈值, cwnd达到阈值后, 开始拥塞避免

    拥塞避免(加法增大), 拥塞窗口cwind 缓慢增大, 以防止网络过早出现拥塞

    乘法减小, 只要出现网络拥塞, 把ssthresh 减为拥塞峰值一半, 同时执行慢开始, 当网络出现频繁拥塞时, ssthresh 值下降很快

    TCP 拥塞控制 - 快重传, 快恢复

    快重传

    快恢复:

    当发送方连续收到三个重复确认, 说明网络出现拥塞

    • 执行乘法减小, 把ssthresh 减为拥塞峰值的一半

    与慢开始不同之处是现在不执行慢开始算法, 即cwnd 现在不回复到初始值

    • 把cwnd 值设置为新的ssthresh值
    • 开始执行拥塞避免算法(加法增大), 使拥塞窗口缓慢的线性增大
    快重传快恢复

    发送窗口的最大值swnd = min(cwnd, rwnd)

    当rwnd < cwnd时, 是接收方的接收能力限制发送窗口的最大值

    当cwnd < rwnd时, 网络拥塞控制发送窗口的最大值

    TCP 序号, 确认号

    序号 序号细节 序号细节1 序号细节2 序号过程 相对值 连接传输过程

    TCP 建立连接 - 3 次握手

    3次握手
    • CLOSED, client处于关闭状态
    • LISENT, server处于监听状态, 等待client连接
    • SYN-RCVD, server接收到了SYN 报文, 当收到client 的ACK 报文后, 进入到ESTABLISHED 状态
    • SYN-SENT, client已发送SYN 报文, 等待server 的第二次握手
    • ESTABLISHED, 已经建立连接

    TCP 建立连接 - 前2 次握手的特点

    SYN 都为1,

    数据部分长度都是0

    TCP 头部长度一般为32 字节

    • 固定头部, 20 字节
    • 选项部分, 12 字节

    双方交换确认一些信息

    • 比如MSS, 是否支持SACK, Window scale(窗口缩放系数)
    • 这些数据存放在TCP 头部选项部分(12 字节)

    为什么是3 次握手不是2 次?

    目的: 防止server 端一直等待, 浪费资源

    如果建立连接只需要2 次握手, 可能出现以下情况

    • 假设client 发出的第一个连接请求报文段, 因为网络延迟, 在连接释放以后的某个时间才到server, 本来是一个早已经失效的连接请求, 但server 收到这个请求后, 误认为client 再次发出的一个新的连接请求, server 向client 发出确认报文段, 同意建立连接
    • 如果上述不采用3 次握手, 那么只要sever 发出确认, 新的连接就建立了
    • 由于是一个失效的连接请求, client 并没有建立与服务器连接的意愿, 也不会向server发送数据. 但是server 却认为新的连接已经建立, 并一直等待, server很多资源就白白浪费了

    第三次握手失败的处理

    • 此时server 的状态为SYN-RCVD, 若等不到client 的ACK, server 会重新发送SYN-ACK包
    • 若server 多次重复发哦送SYN-ACK都等不到client 的ACK, 就会发送RST, 强制关闭连接
    三次握手失败

    TCP 释放连接 - 4 次挥手

    释放连接

    FIN-WAIT-1, 表示主动关闭连接

    • 向对方发送FIN 报文, 此时进入到FIN-WAIT-1 状态

    CLOSED-WAIT, 表示在等待关闭

    • 当对方发送FIN 给自己, 自己会回应一个ACK 报文给对方, 此时则进入到CLOSED-WAIT状态
    • 在此状态下, 需要考虑自己是否还有数据发送给对方, 如果没有, 发送FIN 报文给对方

    FIN-WAIT-2, 只要对方发送ACK 确认后, 主动方就会进入FIN-WAIT-2 状态, 然后等待对方发送FIN 报文

    CLOSING, 罕见状态

    • 表示你发送FIN 报文, 并没有收到对方ACK, 反而收到对方FIN 报文
    • 如果双方几乎同时准备关闭连接的话, 那么久出现双方同时发送FIN 报文的情况, 也会出现CLOSING状态
    • 双方都在关闭连接

    LAST-ACK, 被动关闭一方在发送FIN 报文后, 最后等待对方的ACK 报文

    • 当收到ACK 报文后, 即可进入CLOSED 状态

    TIME-WAIT, 表示收到对方的FIN 报文, 并发送出了ACK 报文, 就等待2MSL 后进入CLOSED状态

    • 如果FIN-WAIT-1 状态, 收到对方同时带FIN 标志和ACK 标志的报文, 可以直接进入到TIME-WAIT 状态, 无需经过FIN-WAIT-2

    CLOSED, 关闭状态

    由于有些状态的时间比较短暂, 所以很难用netstat 命令看到, 比如SYN-RCVD, FIN-WAIT-1

    TCP 释放连接 - 细节

    1. client 发送ACK 后, 需要有个TIME-WAIT 阶段, 等待一段时间, 再关闭连接

      一般是等待2 倍MSL(Maximum Segment Lifetime), 最大分段生存期

      MSL 是TCP 报文在Internet 上的最大生存时间

      每个具体的TCP 实现都必须选择一个确定的MSL, RFC 112 建议2 分钟. 可以防止本次连接中产生的数据包误传到下一次连接中, 因为本次连接中的数据包会在2MSL 时间内消失了

    2. 如果client 发送ACK 后马上释放了, 然后因为网络的原因, server 没有收到client 的ACK, server就会重发FIN, 这时可能出现的情况是

      1. client 没有任何响应, 服务器那边一直等待, 甚至多次重发FIN, 浪费资源
      2. client 有新的应用程序刚好分配同一个端口号, 新的应用程序收到FIN 后马上开始执行断开连接的操作, 原本是要和server 建立连接的

    为什么进行4 次挥手?

    TCP 是全双工通信

    第一次挥手, 主机1 发出FIN 报文时

    • 主机1 告诉主机2 没有数据要发送了, 但是主机1 还是可以接收主机2发来的数据

    第二次挥手, 主机2 返回ACK 报文

    • 主机2 已经知道主机1 没有数据发送了, 但是主机2 还是可以发送数据到主机1

    第三次挥手, 主机2 也发送FIN 报文

    • 主机2 告诉主机1, 主机2 已经没有数据要发送了

    第四次挥手, 主机1返回ACK报文

    • 主机1 已经知道主机2 没有数据发送了, 随后正式断开整个TCP 连接

    相关文章

      网友评论

          本文标题:传输层

          本文链接:https://www.haomeiwen.com/subject/vfupdrtx.html