zoukankan      html  css  js  c++  java
  • 网络读书笔记-运输层

    领会和表达复杂世界背后的简单性的能力是给我罕见和绝妙的礼物 —— Van Jacobson

    运输层和网络层:在协议栈中,运输层刚好位于网络层之上。网络层提供了主机之间的逻辑通信,而运输层为运行在不同主机上的进程之间提供了逻辑通信。运输层只工作在端系统中,运输层协议将来自应用进程的报文移动到网络边缘(即网络层)。

    我们将特别关注因特网协议,即TCP和UDP运输层协议。因特网(更一般地讲是一个 TCP/IP 网络)为应用层提供了两种截然不同的可用传输层协议:一种是UDP(用户数据报协议),它为调用它的应用程序提供了一种不可靠、无连接的服务;另一种是TCP(传输控制协议),它为调用它的应用程序提供了一种可靠的、面向连接的服务。

    在介绍TCP/UDP之前,先来学习运输层的多路复用多路分解:将由网络层提供的主机到主机交付服务延伸到为运行主机上的应用程序提供进程到进程的交付服务。考虑接收主机怎样将一个到达的运输层表文段定向到适当的套接字?为此目的,每个运输层报文段中具有几个字段,在接收端运输层检查这些字段,标识出接收套接字,进而将报文段定向到该套接字。将运输层报文段中的数据交付到正确的套接字的工作称为多路分解。在源主机从不同套接字中收集数据块,并为每个数据块封装首部信息(用于分解)从而生成报文段,然后将报文段传递到网络层,这些工作称为多路复用

    1. 无连接传输:UDP

    UDP 报文段结构:

    图1 UDP报文段结构

    UDP 首部只有4个字段,每个字段由两个字节组成,共8字节。

    1556086144745

    图2 查看UDP报文段结构

    2. 可靠数据传输原理

    2.1 构造 可靠数据传输协议(rdt)

    rdt1.0 经完全可靠信道的可靠数据传输

    考虑了简单的情况,假设底层信道是完全可靠的。发送方和接收方的有限状态机(FSM)定义:

    1555558250207

    rdt2.0 经具有比特差错信道的可靠数据传输

    1555557610168

    为了可靠通信,加上了具有 ACK, NAK 的重传机制,基于自动自动重传机制的可靠数据传输协议称为 自动重传请求(ARQ)协议。为了处理比特差错,ARQ还需要另外三种协议功能来处理存在比特差错情况:差错检测接收方反馈重传(接收方收到差错分组时,发送方重传该分组)

    仅当接收到ACK并离开该状态时才能再次发送数据rdt_send(data),因此,除非发送方确信接收方已正确接收当前分组,否则发送方将不会发送新数据。像rdt2.0这样的协议被称为停等(stop-and-wait)协议

    看起来可以运行,但是有一个致命的缺陷,尤其是没有考虑ACK或NAK分组丢失的情况。

    rdt2.1 rdt2.0 + 序号 用来处理受损的 ACK 和 NAK。

    rdt2.2 在具有比特差错信道上实现的一个无NAK的可靠传输协议;(使用校验和、序号、ACK分组、重传)

    rdt3.0 比特交替协议 (一个可能出错和丢包的信道上可靠传输数据的协议)rdt2.2+定时器

    rdt2.2已经有足够的功能(序号)来处理冗余分组的情况。从发送方观点来看,重传是一种万能灵药。发送方不知道是数据分组丢失还是(接收方回传的)ACK丢失,或者只是该分组或者ACK过度延迟。在所有这些情况下,动作都可采用:重传!为了实现基于时间的重传机制,需要一个倒计时计数器,在一个给定的时间量过期后,可中断发送方。

    优化:因为停等协议利用率太低,所以要提高利用率,使用能够允许发送方发送多个分组而无需等待确认的流水线技术(流水线可靠数据传输协议)。流水线技术对 rdt 可带来如下影响:

    • 必须增加序号范围。
    • 协议的发送方和接收方两端也许必须缓存多个分组。
    • 所需序号范围和对缓冲的要求取决于数据传输协议如何处理丢失、损坏及延时过大的分组。解决流水线的差错恢复有两种基本方法:回退N步(go-back-n, GBN)和 选择重传(selective repeat, SR)。

    1555990601035

    图3.18:停等和流水线发送

    2.2 回退N步 (GBN)

    回退N步(GBN)协议中,允许发送方发送多个分组而不需等待确认,但它也受限在流水线中未确认的分组数不能超过某个最大允许数N。

    1555990756184

    图3.19 在GBN中发送方看到的序号

    在GBN协议中,接收方丢弃所有失序分组,以达到按序将数据交付给上层的任务。(假定现在期望接收分组n, 而分组n+1却到了,采取丢弃分组n+1的策略,直到分组n被正确接收)。

    这种方法的有点是接收缓存简单(即接收方不需要缓存任何失序分组),发送方需维护窗口的上下边界([base, base+N))及下一个序号(nextseqnum)在该窗口的位置,但是接收方需要维护的唯一信息就是下一个按序接收分组的序号(expectedseqnum)。

    1556016332232

    图3.22 GBN操作

    GBN协议中综合了使用序号、累计确认、校验和以及超时/重传操作。

    2.3 选择重传 (SR)

    选择重传(SR)协议通过让发送方仅重传那些它怀疑在接收方出错(即丢失或受损)的分组而避免了不必要的重传。这种个别的、按需的重传要求接收方逐个地确认正确接收的分组。

    1556016413771

    图3.26 SR操作

    我们知道要掌握 TCP 协议,重点应该关注以下几个问题: (极客时间-趣谈网络协议)

    • 顺序问题 ,稳重不乱;
    • 丢包问题,承诺靠谱;
    • 连接维护,有始有终;
    • 流量控制,把握分寸;
    • 拥塞控制,知进知退。

    3. TCP协议

    TCP是因特网运输层的面向连接的可靠运输协议。

    TCP是面向连接的,这是因为在一个应用进程开始向另一个应用进程发送数据之前,这两个进程必须先互相“握手”,即它们必须相互发送某些预备报文段,以建立确保数据传输的参数。TCP连接提供的是全双工服务

    3.1 TCP 报文段结构

    1556073105830

    图3.29 TCP报文段结构

    TCP首部共20字节。包含:16(源端口号)+16(目的端口号)+32(序号)+32(确认号)+4(首部长度)+(6+6)(flags)+16(接收窗口)+16(因特网校验和)+16(紧急数据指针) = 160比特 = 20字节。

    实际抓到的包开始看到的都是Seq=0, 其实是WireShark的设置:

    事实上,握手时 Seq 号并不是从 0 开始的。我们之所以在 Wireshark 上看到 Seq=0 ,是因为 Wireshark 启
    用了 Relative Sequence Number 。如果你想关闭这个功能,可以在 Edit-->Preferences-->protocols-->TCP 里设置。

    设置之后可以看到Seq、Ack与首部数据对应了。

    1556084797493

    图3.30 查看TCP的报文段结构

    序号和确认号:TCP报文段首部中两个最重要的字段是序号字段和确认号字段。这两个字段是TCP可靠传输服务的关键部分。重点,序号和确认号计算:

    Len :该数据段的长度,如图 5 中的 Len=1448 ,注意这个长度不包括 TCP 头。图 5 中虽然 10.32.106.62 发出的两个包 Len=0 ,但其实是有
    TCP 头的。头部本身携带的信息很多,所以不要以为 Len=0 就没意义。
    Ack :确认号,如图 5 中的 Ack = 6577 ,接收方向发送方确认已经收到了哪些字节。
    比如甲发送了 “Seq: x Len: y” 的数据段给乙,那乙回复的确认号就是 x+y ,这意味着它收到了 x+y 之前的所有字节。同样以图 5 为例, 52 号包
    的 Seq=5129, Len=1448 ,所以来自接收方的 53 号包的 Ack=5129+1448=6577 ,表示收到了 6577 之前的所有字节。理论上,接收方回复的 Ack
    号恰好就等于发送方的下一个 Seq 号,所以我们可以看到 54 号包的 Seq 也等于 5129+1448=6577 。

    可靠数据传输:在发送方,TCP的响应无非就是重传有问题的报文段。TCP的差错恢复机制是GBN协议和SR协议的混合体。

    3.2 TCP 三次握手,建立连接

    img

    图3.31 TCP三次握手以及经历的典型的TCP状态序列,左侧客户端右侧服务器端,来自极客时间趣谈网络协议

    客户应用进程通知客户TCP,它想建立一个与服务器上某个进程之间的连接。客户端的 TCP 会用以下方式与服务器中的TCP建立一条TCP连接:

    1. 客户端的TCP首先向服务器的TCP发送一个特殊的TCP报文段。在报文段的首部中的一个标志位(即SYN)被置为1。(因此,这个特殊报文段被称为 SYN报文段。)另外,客户会随机选择一个初始序号client_isn(图3.31中的x),并将此编号放置于该其实的TCP SYN报文段的序号字段seq中。该报文段会被封装在一个IP数据报中,并发送给服务器。(该报文段中不包含应用层数据)。
    2. 一旦包含 TCP SYN 报文段的IP数据报到达服务器主机,服务器会从该数据报中提取出 TCP SYN 报文段,为该TCP连接分配TCP缓存和变量,并向该客户TCP发送允许连接的报文段。(握手第三步之前分配这些缓存和变量,使得TCP易于受到称为SYN洪泛/洪水SYN Flood的拒绝服务攻击DoS)。在报文段首部包含三个重要信息:SYN比特被置为1;TCP 报文段首部的确认号字段ack被置为client_isn+1;服务器选择自己的初始序号server_isn(图3.31中的y)并将其放到TCP报文段首部的序号字段seq中。该允许连接的报文段有时被称为SYNACK报文段。(这个报文段中也不包含应用层数据)
    3. 在收到SYNACK报文段后,客户也要给该连接分配缓存和变量。这最后一个报文段对服务器允许连接的报文段进行了确认(客户通过将y+1放置到TCP报文段首部的确认字段ack中来完成此工作)。连接结束,将SYN置0。

    3.3 TCP 四次挥手,关闭连接

    天下没有不散的宴席,对于TCP也是一样。参与一条TCP连接的两个进程中的任何一个都能终止该连接。

    img

    图3.32 TCP四次挥手以及经历的典型的TCP状态序列,来自极客时间趣谈网络协议

    1556094384113

    图3.40 简洁版本的关闭TCP连接

    从客户关闭连接举例(客户端也可主动关闭该连接):

    客户应用进程发出一个关闭连接命令。这会引起客户TCP向服务器进程发送一个特殊的TCP报文段(让其首部中的一个标志位即 FIN 比特被设置为1),当服务器接收到该报文段后,就向发送方回送一个确认报文段。然后,服务器发送它自己的终止报文段(其FIN比特被置为1)。最后,该客户对这个服务器的终止报文段进行确认。此时,在两台主机上用于该连接的所有资源都被释放了。

    参考

    1. 《计算机网络自顶向下》 第六版
    2. 《Wireshark网络分析就这么简单》
  • 相关阅读:
    重要网址
    线程同步与异步
    常量指针 和 指针常量
    权限设置
    COM组件技术
    抽象类与接口及其派生类的关系
    C++中 #pragma 的使用方法
    [原创].基于SyntaxHighlighter的Verilog HDL高亮组件
    [转载].图解SDRAM工作流程:仓库物语(高手进阶,终极内存技术指南——完整/进阶版)
    [笔记].原来Notepad++也有列模式
  • 原文地址:https://www.cnblogs.com/warcraft/p/10764932.html
Copyright © 2011-2022 走看看