计算机网络笔记-1

简介

  • 这里记录了笔者阅读《计算机网络:自顶向下方法》的一些笔记。笔记有所缩略。
  • 主要关于
    • 第一章:计算机网络和因特网
    • 第二章:应用层
    • 第三章:运输层

第一章:计算机网络和因特网

  • 所有的联网设备称为主机(host)或者端系统(end system)

  • 端系统通过通信链路communication link分组交换机packet switch相连。

    • 分组交换机中最著名的两种是路由器router链路层交换机link-layer switch
    • 一个分组所经历的一系列通信链路分组交换机称为通过该网络的路径route/path
  • 网络核心

    通过网络链路和交换机移动数据有两种基本方法:电路交换分组交换

    • 分组交换:

      image-20210507194417422

      • 在各种网络应用中,端系统彼此交换报文message,报文能够包含协议设计者需要的任何东西,例如控制功能、数据等。

      • 为了从源端系统向目的端系统发送一个报文,源将长报文划分为较小的数据块,称之为分组packet。

      • 多数分组交换机在链路的输入端使用存储转发传输store-and-forward transmission机制。指的是在交换机能够开始向输出链路传输该分组的第一个比特之前,必须接收到整个分组。

        image-20210507193626489

      • 排队时延和分组丢失

        • 每台分组交换机有多条链路与之相连。对于每条相连的链路,该分组交换机具有一个输出缓存/输出队列,用于存储路由器准备发往那条链路的分组。
        • 如果到达的分组需要传输到某条链路,但发现该链路正忙于传输其他分组,该到达分组必须在输出缓存中等待,因此除了存储转发时延以外,分组还要承受输出缓存的排队时延。如果该缓存已被完全装装满,则将出现分组丢失packet loss
    • 电路交换

      • 当两台主机通信时,该网络在两台主机之间创建一条专用的端到端连接。因此必须在两条链路的每条上先预留一条电路。

        image-20210507194445844

      • 电路交换网络中的复用

        链路中的电路是通过频分复用FDM时分复用TDM来实现。

        • 对于频分复用FDM来说,链路的频谱由跨越链路创建的所有连接共享,为每个连接专用一个频段,例如收音机。

        • 对于时分复用TDM来说,时间被划分为固定区间的帧,每帧被划分为固定数量的时隙。网络跨越一条链路创建一条连接时,网络在每个帧中为该连接指定一个时隙。这些时隙专门由该链接单独使用。

        image-20210507195514761

    • 分组交换比电路交换更有效:

      • 提供更好的带宽共享。
      • 更简单、有效,成本更低。

      电路交换不考虑需求,而预先分配了传输链路的使用,使得效率较低。分组交换按需分配链路使用,效率较高。

  • 分组交换的时延

    • 节点处理时延:检查分组首部和决定将该分组导向何处所需要的时间,以及检查比特级别的差错等时间。

    • 排队时延:在队列中,当分组在链路上等待传输时,它经受排队时延。一个特定分组的排队时延长度取决于先期到达的正在排队等待向链路传输的分组数量。

    • 传输时延:传输时延是将特定分组的所有比特发射进链路所需要的时间。传输时延与分组大小呈正相关。

    • 传播时延:从该链路的起点到下一个路由器传播所需要的时间。

      注意:传输时延和传播时延不是一回事,两者概念完全不同。

    四个相加即总时延。$d_{nodal}=d_{proc}+d_{queue}+d_{trans}+d_{prop}$

  • 协议分层

    • 应用层:网络应用程序以及他们的应用层协议存留的地方,例如http、smtp等。

    • 运输层:运输层在应用程序端点之间传送应用层报文,有以下两种运输协议:

      • TCP:将长报文划分为短报文,提供拥塞控制机制。
      • UDP:向应用程序提供无连接服务,不提供不必要服务,没有可靠性,没有流量控制,没有拥塞控制。

      将运输层的分组称为报文段segment

    • 网络层:网络层负责将称为数据报datagram的网络层分组从一台主机移动到另一台主机。网络层包括著名网际协议IP。

    • 链路层:网络层通过源和目的地之间的一系列路由器来 路由(注意这是动词) 数据报。为了将分组从一个结点移动到路径上的下一个结点,网络层必须依靠该链路层的服务。

      将链路层分组称为帧frame。链路层的任务是将整个帧从一个网络元素移动到邻近的网络元素。该层协议与链路层相关。

    • 物理层:物理层的任务是将每个帧中的一个个比特从一个节点移动到下一个节点。该层协议与链路相关,并进一步与链路的实际传输媒体相关,例如双绞铜线、单模光纤等。

    各层的所有协议称为协议栈

    image-20210507202004763

第二章:应用层

1. 因特网提供的运输服务

  • TCP服务

    • 面向连接的服务

      在应用层数据报文开始流动之前,TCP让客户和服务器互相交换运输层控制信息。这个握手过程提醒客户和服务器为大量分组的到来做好准备。

      三次握手完成后,一个TCP连接就在两个进程之间建立,该连接是全双工的,即连接的双方可以在此连接上同时进行报文的收发

      当应用程序结束报文发送时,必须拆除该连接。

    • 可靠的数据传送服务

      通信进程能够依靠TCP,无差错、按顺序交付所有发送的数据,无字节丢失或冗余。

    • 具有拥塞控制机制。

    安全套接字SSL:TCP的加强版本,即加密版本。

    SSL有自己的套接字API,应用向SSL套接字传递明文数据,发送主机中SSL加密该数据并将加密后数据传递给发送端TCP套接字。接收端套接字接收到加密数据,将其解密,并通过SSL套接字将明文数据传递给接收进程。

  • UDP服务

    • 是一种不提供不必要服务的轻量级运输协议,仅提供最小服务。
    • UDP是无连接的,因此两进程通信前没有握手过程。
    • UDP协议提供不可靠数据传送服务,即UDP协议不保证报文到达接受进程,同时接收到的报文也可能是乱序的。无拥塞控制机制。

2. 应用层协议

a. http

  • 请求报文样例如下:

    1
    2
    3
    4
    5
    GET /somedir/page.html HTTP/1.1
    Host: www.someschool.edu
    Connection: close
    User-agent: Mozilla/5.0
    Accept-language: fr

    具体请求报文通用格式如下:

    image-20210507204906032

  • 响应报文样例如下:

    1
    2
    3
    4
    5
    6
    7
    8
    9
    HTTP/1.1 200 OK
    Connection: close
    Date: Tue, 18 Aug 2015 15:44:04 GMT
    Server: Apache/2.23 (CentOS)
    Last-Modified: Tue, 18 Aug 2015 15:11:03 GMT
    Content-Length: 6821
    Content-Type: text/html

    (data data data data data ...)

    具体通用格式如下:

    image-20210507205312687

  • web 缓存

    • Web缓存也称代理服务器,其工作流程如下:

      • 浏览器创建一个到Web缓存器的TCP连接,并向Web缓存器中的对象发送一个 HTTP 请求。

      • Web缓存器进行检查

        • 如果本地存储了对象副本,则Web缓存器向客户浏览器用HTTP响应报文返回该对象。

        • 如果没有存储该对象,则打开一个与该对象的初始服务器的TCP连接,并在该连接上发起一个HTTP请求。受到请求后,初始服务器向该web缓存器发送具有该对象的http响应。

          当Web缓存器接收到对象后,在本地存储空间存储一份副本,并向客户的浏览器用HTTP响应报文发送该副本。

    • 存放在Web缓存器中的对象副本可能是陈旧的,而http协议允许缓存器证实它的对象是最新的,即条件GET方法:

      • 请求报文使用 GET 方法
      • 请求报文中包含一个 If-Modified-Since 首部行

      如果Web缓存器向初始服务器发送条件get报文时:

      • 目标对象没有发生改变,则响应报文中的body为空。
      • 目标对象已经改变,响应报文中存放新的对象。

b. DNS

  • 主机的一种标识方式是使用其主机名hostname

  • DNS是

    • 一个由分层的DNS服务器实现的分布式数据库。
    • 一个使得主机能够查询分布式数据库的应用层协议。
  • DNS提供的服务

    • 主机名到IP地址的转换

    • 主机别名:有着复杂主机名的主机能够拥有一个或多个别名。

      例如一台名为relay1.west-coast.enterprise.com的主机,可能还有两个别名为enterprise.comwww.enterprise.com的主机。在这种情况下,relay1.west-coast.enterprise.com也称为规范主机名canonical hostname。主机别名比主机规范名更加容易记忆。

    • 邮件服务器别名:电子邮件应用程序可以调用DNS,对提供的主机名别名进行解析,以获得该主机的规范主机名及其IP地址。

    • 负载分配:DNS也用在冗余的服务器之间进行负载分配。

  • DNS工作机理概述

    • 分布式、层次数据库

      • 为了处理扩展性问题,DNS使用了大量的DNS服务器,以层次方式组织。
      • 有三种类型的DNS服务器
        • 根DNS服务器:提供顶级域服务器的ID地址。
        • 顶级域(Top-Level Domain)DNS服务器:对于每个顶级域(例如com、org、net等)和所有国家的顶级域(如uk、fr等),都有TLD服务器。TLD服务器提供权威DNS服务器的IP地址。
        • 权威DNS服务器:在因特网上具有公共可访问主机的每个机构必须提供公共可访问的DNS记录,这些记录将这些主机的名字映射为IP地址。一个组织机构的权威DNS收藏了这些DNS记录。

      image-20210508203109038

      • 本地DNS服务器:严格来说不属于DNS服务器的层次结构。本地服务器起着代理的作用,将DNS请求转发到DNS服务器层次结构中。

        DNS查询分为两种:递归查询迭代查询

        • 迭代查询

          image-20210508204520770

        • 递归查询

          image-20210508204559893

    • DNS缓存

      • 原理:当某DNS服务器接收一个DNS回答时,DNS缓存能将映射缓存在本地存储器中。

        如果在DNS服务器中缓存了一台主机/IP地址对,另一个对相同主机名的查询到达该DNS服务器时,该DNS服务器就能提供所要求的IP地址,即使它不是该主机名的权威服务器。

      • 由于主机和主机名与IP地址间的映射并不是永久的,DNS服务器在一段时间后将丢弃缓存的信息。

      • 本地DNS服务器也能够缓存TLD服务器的IP地址,因而允许本地DNS绕过查询链中的根DNS服务器。因为缓存的存在,除了少数DNS查询以外,根服务器被绕过了。

  • DNS记录和报文

    • 共同实现DNS分布式数据库的所有DNS服务器存储了资源记录(Resource Recode, RR),其中提供了主机名到IP地址的映射。每个DNS回答报文中包含了一条或多条的资源记录。

    • 资源记录是一个包含了下列字段的4元组:(Name, Value, Type, TTL)

      其中,TTL是该记录的生存时间,决定了资源记录应当从缓存中删除的时间

      Name和Value的值取决于Type:

      • 如果Type = A,则 Name 是主机名, Value 是该主机名对应的IP地址。即一条类型为A的资源记录提供了标准的主机名到IP地址的映射。例如 (relay1.bar.foo.com, 145.37.93.126, A)

      • 如果Type = NS,则 Name 是一个域(例如foo.com),而 Value 是个知道如何获取该域中主机IP地址的权威DNS服务器的主机名。这个记录用于沿着查询链来路由DNS查询。例如 (foo.com, dns.foo.com, NS)

      • 如果 Type = CNAME,则 Value 是个别名为 Name 的主机对应的规范主机名。该记录能够向查询的主机提供一个主机名对应的规范主机名。例如 (foo.com, relay1.bar.foo.com, CNAME)

      • 如果Type = MX,则 Value 是个别名为 Name 的邮件服务器的规范主机名。例如 (foo.com, mail.bar.foo.com, MX)。MX记录允许邮件服务器主机名具有简单的别名。

        注意:通过MX记录,一个公司的邮件服务器和其他服务器(例如Web服务器)可以使用相同的别名。为了获取邮件服务器的规范主机名,DNS客户应该请求一条MX记录;而为了获取其他服务器的规范主机名,应该请求CNAME记录。

      如果一台DNS服务用于某特定主机名的权威DNS服务器,那么该DNS服务器会有一条包含用于该主机名的类型A记录

      如果服务器不是用于某主机名的权威DNS服务器,那么该服务器将包含一条类型NS记录,该记录对应于包含主机名的域;同时还将包括一条类型A记录,提供在NS记录的Value字段中的DNS服务器的IP地址

    • DNS报文格式如下,只有查询和回答两种报文,并且格式相同:

      image-20210509000647692

      • 前12个字节是首部区域,其中有几个字段。
        • 第一个字段(标识符)是一个16比特的数,用于标识该查询。该标识符会被复制到对查询的回答报文中,以便让客户用它来匹配发送的请求和接收到的回答。
        • 标志字段中含有若干标志。
          • 1比特的 “查询/回答” 标志位指出报文是 查询报文0 还是 回答报文1
          • 当某DNS服务器是所请求名字的权威DNS服务器时,1比特的 “权威的” 标志位将会被置在回答报文中。
          • 如果客户在该DNS服务器没有某记录时,希望它执行递归查询,将设置1比特的 “希望递归” 标志位。如果该DNS服务器支持递归查询,则在回答报文中会对1比特的 “递归可用” 标志位置位。
      • 问题区域包含着正在进行的查询信息。其中,该区域包括
        • 名字字段,包含正在被查询的主机名字
        • 类型字段,指出有关该名字的正被询问的问题类型,例如主机地址是与一个名字相关联(类型A)还是与某个名字的邮件服务器相关联(类型MX)。
      • 在来自DNS服务器的回答中,回答区域包含了对最初请求的名字的资源记录。回答报文中的回答区域可以包含多条RR,因此一个主机名能够有多个IP地址,例如负载均衡
      • 权威区域包含了其他权威服务器的记录。
      • 附加区域包含了其他有帮助的记录。例如对于一个MX请求的回答报文的回答区域包含了一条资源记录,提供了邮件服务器的规范主机名。而附加区域中包含了一个类型A记录,提供用于该邮件服务器的规范主机名的IP地址

3. 套接字编程

a. UDP编程

image-20210508165739385

  • UDPClient.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    from socket import *
    serverName = 'hostname'
    serverPort = 12000
    clientSocket = socket(AF_INET, SOCK_DGRAM)
    message = raw_input('Input lowercase sentence:')
    clientSocket.sendto(message.encode(), (serverName, serverPort))
    modifiedMessage, serverAddress = clientSocket.recvfrom(2048)
    print(modifiedMessage.decode())
    clientSocket.close()
  • UDPServer.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    from socket import *
    serverPort = 12000
    serverSocket = socket(AF_INET, SOCK_DGRAM)
    serverSocket.bind(('', serverPort))
    print("The server is ready to receive")
    while True:
    message, clientAddress = serverSocket.recvfrom(2048)
    modifiedMessage = message.decode().upper()
    serverSocket.sendto(modifiedMessage.encode(), clientAddress)

b. TCP编程

image-20210508165807956

  • TCPClient.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    from socket import *
    serverName = 'servername'
    serverPort = 12000
    clientSocket = socket(AF_INET, SOCK_STREAM)
    clientSocket.connect((serverName, serverPort))
    sentence = raw_input('Input lowercase sentence:')
    clientSocket.send(sentence.encode())
    modifiedSentence = clientSocket.recvfrom(1024)
    print('From Server: ', modifiedSentence.decode())
    clientSocket.close()
  • TCPServer.py

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    from socket import *
    serverPort = 12000
    serverSocket = socket(AF_INET, SOCK_STREAM)
    serverSocket.bind(('', serverPort))
    serverSocket.listen(1)
    print("The server is ready to receive")
    while True:
    connectionSocket, addr = serverSocket.accept()
    sentence = connectionSocket.recvfrom(1024).decode()
    capitalizedSentence = sentence.upper()
    connectionSocket.send(capitalizedSentence.encode())
    connectionSocket.close()

第三章:运输层

1. 简述

  • 运输层协议为运行在不同主机上的应用进程之间提供了逻辑通信logic communication功能。从应用程序的角度来看,通过逻辑通信,运行不同进程的主机好像直接相连一样。

  • TCP和UDP是运输层协议中的一种,但运输层协议不是只有这两种

  • 将运输层TCP/UDP分组称为报文段segment,将网络层分组称为数据报datagram

  • 因特网网络层协议中有一个协议为网际协议IP,其服务模型是尽力而为交付服务,称为不可靠服务。每台主机至少有一个网络层地址,即IP地址。

  • 将主机间交付扩展到进程间交付被称为运输层的多路复用与多路分解

    • 将运输层报文段中的数据交付到正确的套接字的工作称为多路分解

    • 从不同套接字中收集数据块、为每个数据块封装上首部信息,以生成报文段,并最终传递到网络层。这些工作统称为多路复用

    • 运输层多路复用要求

      • 套接字有唯一标识符。
      • 每个报文段有特殊字段来指示该报文段索要交付到的套接字。通常这些字段包含源端口号字段目的端口号字段(还有一些其他字段)。
    • 运输层实现分解服务的过程

      • 当报文到达主机时,运输层检查报文段中的目的端口号,并将其定向到相应的套接字。
      • 报文段中的数据通过套接字进入其所连接的进程。
    • 无连接的多路复用与多路分解

      一个UDP套接字是由一个二元组全面标识,该二元组包含一个目的IP地址和一个目的端口号

      因此如果两个UDP报文段有不同的源IP地址/源端口号,但具有相同的目的IP地址和目的端口号,则两个报文段将通过相同的目的套接字被定向到相同的目的进程。

    • 面向连接的多路复用与多路分解

      一个TCP套接字是由一个 四元组(源IP地址,源端口号,目的IP地址,目的端口号) 来标识。

      两个具有不同源IP地址或源端口号的到达TCP报文段将被定向到两个不同的套接字。

2. 无连接运输:UDP

  • UDP优点

    • 关于发送什么数据以及何时发送的应用层控制更为精细。与TCP的拥塞控制机制相反,UDP会立即将应用层的数据打包并立即传递给网络层。
    • 无需连接建立。UDP无需三次握手,不需要任何准备即可进行数据传输,因此不会引入建立连接的时延。
    • 无连接状态。TCP需要在端系统中维护连接状态,此连接状态中包括接受和发送缓存、拥塞控制参数以及序号与确认号的参数。而UDP不维护连接状态,因此不跟踪这些参数,就可以支持更多活跃客户。
    • 分组首部开销小。每个TCP报文段都有20字节的首部开销,而UDP仅有8字节的开销。
  • UDP报文段结构

    image-20210508163648687

  • UDP提供差错检测功能:发送方的UDP对报文段中的所有16比特字的进行反码运算。求和时遇到的任何溢出都将被回卷。得到的结果被放在UDP报文段中的检验和字段。

    回卷:把溢出的最高位1和低16位做加法运算。

    这样,接收方将全部的16比特字相加,如果分组没有引入差错,则在接收方处该和将为1111111111111111。如果存在任意一个位置的比特为0,则说明该分组中出现差错。

3. 可靠数据传输

1. 构建可靠传输数据协议

  • 可靠数据传输为上层实体提供的服务抽象是:数据可以通过一条可靠的信道进行传输。借助于可靠信道,传输数据比特就不会不会受到损坏或丢失,并且所有数据都是按照其发送顺序进行交互。

    实现这种服务抽象是可靠数据传输协议的责任,但通常该协议的下层协议是不可靠的,因此任务较为复杂。

    例如:TCP是在不可靠的(IP)端到端网络层之上实现的可靠数据传输协议。

  • 底层信道在分组的传输或缓存的过程中,可能会产生比特差错。当检测到这类错误时,发送方需要重传对应的分组,并等待接收方发送肯定确认否定确认的控制报文。这些控制报文使得接收方可以让发送方知道哪些内容被正确接收,那些内容接收有误并因此需要重复。在计算机网络中,基于这样重传机制可靠数据传输协议称为自动重传请求(Automatic Repeat reQuest, ARQ)

    更重要的是,ARQ协议还需要另外三种协议功能来处理存在比特差错的情况:

    • 差错检测。需要一种机制以使接收方检测到何时出现了比特差错。这里使用比特校验技术(想想UDP校验)。
    • 接收方反馈。由于发送方和接收方通常在不同的端系统上运行,因此发送方要了解接收方情况的唯一途径是让接收方提供明确的反馈信息给发送方。口述报文中的肯定确认ACK否定确认NAK就是这种反馈的例子。
    • 重传。接收方收到有差错的分组时,发送方将重传该分组文。

    需要注意的是,接收方返回的 ACK/NAK 报文同样有受损或丢包的风险。当发送方收到含糊的 ACK/NAK 分组时,只需重传分组即可,但这会在信道中引入冗余分组。冗余分组的困难点在于,接收方无法事先知道接收到的分组是新的还是一次重传。

    解决这个问题的一个简单方法是:在数据分组中添加一新字段,让发送方对其数据分组编号,即将发送数据分组的序号放在该字段,之后接收方只需检查序号即可确定收到的分组是否是一次重传。

  • 除了比特受损以外,底层信道还会丢包。因此可靠数据传输协议必须处理另外两个问题:如何检测丢包 & 发送丢包后该做什么。根据上文,我们可以很容易的给出后一个问题的答案——重传。但对于第一个如何检测丢包,我们需要进一步的研究一下。

    发送方等待足够长的时间以确定分组是否已经丢失。实践中发送方根据特定算法选择一个时间值,以判定是否丢包(注意是判定不是确保)。如果在这个时间内没有收到ACK则重传该分组。

    需要注意的是,如果一个分组经历特别大的时延,发送方就可能重新发送该分组,即便原分组和其ACK都没有丢失。而这种情况就引入了冗余数据分组

    为了实现基于时间的重传机制,需要一个倒计时定时器,在一个给定的时间量过期后,中断发送方,使其重传。

  • 最终,实现的可靠传输数据协议的状态机图如下所示:

    image-20210514200231320

    这里同样有一个图说明运行时可能产生的各类情况:

    image-20210514200835917

    检验和序号定时器肯定和否定确认分组这些技术中,每种机制都在可靠传输协议的运行中起到了必不可少的作用,至此组合而成一个可靠传输数据协议

2. 流水线可靠传输数据协议

上文中所实现的可靠传输数据协议是一个停等协议,即只有确保接收方正常接受当前分组后,才会继续发送下一个分组。停等协议的性能极其低下,并且其信道利用率也非常的低,故允许发送方发送多个分组而无需等待确认是一个必然的选择。

由于许多从发送方向接收方输送的分组可以被看做是填充到一条流水线中,因此该技术称为流水线。流水线技术对可靠数据传输协议带来的影响如下:

  • 必须增加序号范围。因为每个输送中的分组必须有一个唯一的序号,并且或许有多个在输送中的未确认报文。
  • 协议中的发送方和接收方两端也许不得不缓存多个分组。发送方至少要缓存那些已发送但没有确认的分组;接收方需要缓存那些已正确接受的分组。
  • 所需序号范围和对缓冲的要求取决于数据传输协议如何处理丢失、损坏以及延时过大的分组。

对于流水线的差错恢复有两种基本方法:回退N步(Go-Back-N, GBN)选择重传(Selective Repeat, SR)

1) 回退N步

回退N步协议允许发送方发送多个分组而不需等待确认,但受限于在流水线中未确认的分组数不能超过某个最大允许数N。以下显示了发送方看到的GBN协议的序号范围:

基序号:最早未确认分组的序号

下一个序号:最小未使用序号

N常被称为窗口长度,因此GBN协议称为滑动窗口协议。

  • $[0, base-1]$:已经发送并被确认的分组
  • $[base, nextseqnum-1]$:已经发送但未被确认的分组
  • $[nextseqnum, base+N-1]$:用于那些要被立即发送的分组
  • $[base+N, \infty)$:暂时不能被使用,直到移动窗口。

image-20210514202515628

GBN的发送方必须响应三种类型的事件:

  • 上层调用。当上层调用 rdt_send 时,发送方首先检查发送窗口是否已满,如果未满则产生一个分组并发送。如果窗口已满则隐式指示上层该窗口已满。
  • 收到一个ACK。GBN协议中,对序号为n的分组的确认采取累计确认方式,表示接收方已正确接收到序号为n的以前且包括n在内的所有分组。
  • 超时事件。定时器用于恢复数据或确认分组的丢失。如果出现超时,则发送方重传所有已发送但还未被确认过的分组。

GBN的接收方动作较为简单:如果一个序号为n的分组被正确接收到,并且按序,则接收方为n发送一个ACK,并将该分组中的数据部分交付到上层。其他情况下则丢弃该部分并为最近按序接收的分组重新发送ACK。

以下是一个运行中的GBN流程图:

image-20210514204430755

2) 选择重传

GBN协议可能会重传许多本没必要重传的分组,从而影响性能。SR协议通过让发送方仅重传那些它怀疑在接收方出错的分组,从而避免了不必要的重传。这种个别的、按需的重传要求接收方逐个的确认正确接收的分组。

SR协议同样使用窗口长度N来限制流水线中未完成、未被确认的分组数。但与GBN不同的是,发送方已经收到了对窗口中某些分组的ACK。

image-20210514205328078

SR接收方将确认一个正确接收的分组而不管其是否按序。失序的分组将被缓存直到所有的丢失分组全被收到为止,此时才可以将一批分组按需交付给上层。需要注意的是:接收方会重新确认(而不是忽略)已收到过的那些序号小于当前窗口基序号的分组,因为发送方和接收方的窗口不总是一致

以下是出现丢包时SR操作的简单例子:

image-20210514205526638

3. 可靠数据传输机制及其用途的总结

  • 检验和:用于检测在一个传输分组中的比特错误。
  • 定时器:用于超时/重传一个分组。
  • 序号:用于为从发送方流向接收方的数据分组按顺序进行编号。
  • 确认:接收方用于告诉发送方一个分组或一组分组已被正确的接收到了。
  • 否定确认:接收方用于告诉发送方某个分组未被正确的接收。
  • 窗口、流水线:发送方也许被限制仅发送那些序号落在一个指定范围内的分组。

4. 面向连接的运输:TCP

  • TCP被称为是面向连接的,因为在一个应用进程可以开始向另一个应用进程发送数据之前,这两个进程必须先相互发送某些预备报文段,以建立确保数据传输的参数,这个过程称为握手。连接的双方都将初始化与TCP连接相关的许多TCP状态变量。

    注意:TCP的连接,是一条逻辑连接,共同状态仅保留在两个通信端系统的TCP程序中。中间的网络元素不会维持TCP连接状态,它们看到的只是数据报,而不是连接。

    同时TCP还是全双工、点对点服务。

  • TCP 可从发送缓存中取出并放入报文段中的数据数量受限于最大报文段长度(Maximum Segment Size, MSS)。而MSS通常根据最初确定的由本地发送主机发送的最大链路层帧长度(即最大传输单元Maximum Transmission Unit, MTU)来设置。设置该MSS要保证一个TCP报文段加上TCP/IP首部长度将适合单个链路层帧。

a. TCP报文段结构

image-20210514212456035

  • 源端口号目标端口号:用于多路复用/分解来自或送到上层应用的数据。

  • 32bit的序号字段和32bit的确认号字段。

  • 16bit的接收窗口字段:用于流量控制,表示接收方愿意接受的字节数量。

  • 4bit的首部长度字段:表示以32bit为单位的TCP首部长度。由于TCP选项字段的原因,TCP首部的长度是可变的。(通常情况下,选项字段为空,因此TCP首部的典型长度为20字节)。

  • 可选与变长的选项字段

  • 6bit的标志字段

    • ACK: 指示确认字段中的值是有效的。
    • RST、SYN、FIN:用于连接与拆除。
    • CWR、ECE:明确拥塞通告中使用。
    • PSH:表示接收方应该立即将数据交给上层
    • URG:表示报文段里存在着被发送端的上层实体置为紧急的数据。紧急数据的最后一个字节由16bit的紧急数据指针字段指出。当紧急数据存在并给出指向紧急数据尾指针的时候,TCP必须通知接收端的上层实体。

    在实践中,PSH、URG和紧急数据指针并没有使用。

b. 序号和确认号

  • 序号:TCP把数据看成一个无结构有序的字节流。序号建立在传送的字节流之上,而不是建立在传送的报文段的序列之上。因此一个报文段的序号是该报文段首字节的字节流编号

    image-20210514213733944

  • 确认号:TCP是全双工的,因此主机A在向主机B发送数据的同时,也可能会受到来自主机B的数据。从主机B到达的每个报文段中都有一个序号用于从B流向A的数据。主机A填写进报文段的确认号是主机A期望从主机B受到的下一字节的序号。

    因为TCP只确认该流中至第一个丢失字节为止的字节,因此TCP被称为提供累计确认。若TCP收到乱序的报文段时,实践中最常用的做法是接收方保留失序的字节,并等待缺少的字节以填补该间隔。

  • 一个简单例子如下所示:

    image-20210514215113475

c. 往返时间的估计与超时

  • TCP使用超时/重传机制来处理报文段的丢失问题。超时时间间隔长度必须大于该连接的往返时间(RTT),即从一个报文段发出到它被确认的时间,否则会造成不必要的重传。

  • 估计往返时间

    • 报文段的样本RTT(这里表示为SampleRTT)就是从某报文被发出到对该报文段的确认被收到之间的时间量。大多数TCP的实现仅在某个时刻做一次SampleRTT测量,而不会为每次发送的报文段测量一个SampleRTT。

    • TCP维持一个 SampleRTT 均值(称为 EstimatedRTT),一旦获得一个新 SampleRTT 时,TCP就会根据下列公式来更新 EstimatedRTT:

      $EstimatedRTT = (1 - \alpha) * EstimatedRTT + \alpha* SampleRTT$

      RFC 6298 中给出的 alpha 推荐值为 0.125。

    • 除了估算 RTT外,测量RTT的变化也是有价值的。RFC6298定义了RTT偏差 DevRTT,用于估算SampleRTT 一般会偏离 EstimatedRTT 的程度:

      $DevRTT = (1 - \beta) * DevRTT + \beta * |SampleRTT - EstimatedRTT|$

  • 设置和管理重传超时间隔

    在TCP的确定重传超时间隔的方法中,EstimatedRTT 和 DevRTT 考虑到了显示的情况,因此最终的间隔为:$TimeoutInterval = EstimatedRTT + 4 * DevRTT$

    推荐初始的TimeoutInterval的值为1s。

d. 可靠数据传输

  • 实现机制:该部分中具体实现机制的大部分细节与上文中的可靠数据传输协议相同。

  • 超时间隔加倍:每次TCP重传时都会将下一次的超时间隔设为先前值的两倍,而不是由EstimatedRTT和DevRTT推断出的值。

  • 快速重传

    • 冗余ACK的生成过程:当TCP接收方检测到了数据流中的间隔时(该间隔可能是报文段丢失或重新排序造成),它只会对已经接收到的最后一个按序字节数据进行重复确认(即产生一个冗余ACK)。
    • 验证丢包原因:由于发送方经常发送大量的报文段,如果一个报文段丢失则很有可能引发大量冗余ACK。如果TCP发送方接收到对相同数据的3个冗余ACK,则说明跟在这个已被确认过3次的报文段之后的报文段已经丢失。此时执行快速重传,在报文段定时器过期之前重传丢失的报文段。
  • TCP差错恢复机制

    • TCP确认是累计式的,正确接收但失序的报文段是不会被接收方逐个确认

      注意:不会被逐个确认不代表会被丢弃。

    • TCP发送方仅需维持已发送过但未被确认的字节的最小序号下一个要发送的字节的序号

    • 许多TCP实现会将正确接收但失序的报文段缓存起来。

    • 对TCP提出的修改意见是选择确认。它允许TCP接收方有选择地确认失序报文段,而不是累计地确认最后一个正确接收的有序报文段。

    TCP的差错恢复机制是 GBN协议和SR协议的混合体。

e. 流量控制

  • TCP为应用程序提供流量控制服务以消除发送方使接收方缓存溢出的可能性。

  • TCP发送方也可能因为IP网络的拥塞而被设置,这种形式的发送方的控制被称为拥塞控制

    注意:拥塞控制和流量控制不同,需要区分开来。

  • TCP通过让发送方维护一个称为接收窗口的变量来提供流量控制。接受窗口用于告诉发送方当前接收方还有多少可用的缓存空间。TCP是全双工通信,在连接两端的发送方都各自维护一个接收窗口。

    image-20210515000223929

    假设主机A通过一条TCP连接向主机B发送一个大文件。则主机B通过把当前的 接收窗口rwnd 值放入它发给主机A的报文段接收窗口字段中,通知主机A在该连接的缓存中还有多少可用空间。

  • 还有一个问题:假设主机B的接收缓存已满,使得 rwnd = 0,并且主机B没有任何数据要发给主机A(这种假设是为了确保主机AB之间没有任何的分组通信)。则因为主机B上的应用进程清空缓存时,TCP不会向主机A发送带有 rwnd 新值的新报文段,这样就会使得主机A无法知道主机B的接收缓存已经有新的空间了。因此主机A将会被阻塞,而无法再发送数据

    对于这个问题,TCP规范中要求:**当主机B的接收窗口为0时,主机A继续发送只有一个字节数据的报文段,这些报文段将会被接收方确认。**等到最终主机B的缓存清空,返回的确认报文中将包含一个非零的 rwnd 值。

f. TCP 连接管理

  • TCP连接流程

    • 客户端TCP首先向服务器端的TCP发送一个特殊TCP报文段。该报文段中不包含应用层数据,而是在报文段首部设置 SYN 比特为1. 该特殊报文段被称为 SYN 报文段

      同时,客户端会随机选择一个初始序号 client_isn,并将此编号放置进该起始的TCP SYN 报文段的序号字段中。

      注意:适当的随机选择 client_isn 在避免某些安全性攻击方面起到了一定的作用。

    • 当 TCP SYN 报文段到达服务器主机,则服务器会为该TCP连接分配 TCP 缓存和变量,并向该客户TCP发送允许连接的报文段。

      注意:提前分配缓存和变量可能受到 SYN 攻击。

      该报文段也不包含应用层数据,而是设置

      • SYN 比特为1
      • TCP报文首部的确认号为 client_isn + 1
      • TCP报文首部的序号字段为 服务器的初始序号 server_isn 。

      该允许连接的报文段被称为 SYNACK报文段

    • 当客户端收到 SYNACK 报文段时,客户端也为该连接分配缓存和变量。之后客户端向服务器发送最后一个报文段,对服务器的允许连接报文进行确认(客户端将值server_isn + 1防止进TCP报文段首部的确认字段)。由于连接已经建立,因此SYN比特置0

      在这个确认报文中,可以带上客户端到服务器的数据

    为了创建连接,TCP会在两台主机之间发送3个分组,因此这个连接过程通常称为三次握手

    image-20210515092421032

  • TCP连接拆除

    参与一条TCP连接的两个进程中的任何一个都能终止该连接。

    image-20210515092825158

g. 拥塞控制原理

  • 拥塞原因与代价

    • 假设主机A、B在容量为R的共享式输出链路上传播。当发送速率接近 R/2 时,平均使用时延将会越来越大。当发送速率超过 R/2 时,路由器中的平均排队分组数就会无限增长,源与目的地之间的平均时延也会变成无穷大。

    • 发送方必须执行重传以补偿因为缓存溢出而丢弃的分组。

    • 发送方在遇到大的时延时所进行的不必要重传会引起路由器利用其链路带宽来转发不必要的分组副本

    • 当一个分组沿着一条路径被丢弃时,每个上游路由器用于转发该分组到丢弃该分组而使用的传输容量最终被浪费掉了。

  • 拥塞控制方法

    • 端到端拥塞控制:由于网络层没有为运输层提供显式支持,因此即便网络中存在拥塞,端系统也必须通过对网络行为的观察来推断。例如通过超时或冗余ACK确认。
    • 网络辅助的拥塞控制:在网络辅助的拥塞控制中,路由器向发送方提供关于网络中拥塞状态的显式反馈信息。这类拥塞信息从网络反馈到发送方通常有两种方式:
      • 直接反馈信息:由网络路由器发给发送方。这种方式通常采用一种阻塞分组的形式。
      • 更通用的第二种形式:路由器标记或更新从发送方流向接收方的分组中的某个字段来表示拥塞的产生。当收到一个标记的分组后,接收方就会向发送方通知该网络拥塞指示。

h. TCP 拥塞控制

  • TCP采用的方式是让每一个发送方根据所感知到的网络拥塞程度来限制其能向连接发送流量的速率。

    运行在发送方的 TCP 拥塞控制机制跟踪一个额外的变量:拥塞窗口cwnd。它限制了一个TCP发送方能向网络中发送流量的速率。即 $LastByteSend - LastByteAcked <= min{cwnd, rwnd}$。发送速率为$min{cwnd, wrnd} / RTT$ 字节/秒。

  • TCP发送方怎样确定它应当发送的速率?

    • 一个丢失的报文段表意味着拥塞。因此当丢失报文段时应当降低TCP发送方的速率。
    • 一个确认报文段表示该网络正在向接收方交付发送方的报文段,因此当对先前为确认报文段的确认到达时,能够增加发送方的速率。
    • 带宽探测。
  • TCP拥塞控制算法

    • 慢启动

      • 慢启动起始阶段

        在慢启动状态,cwnd的值以1个MSS开始并且每当传输的报文段首次被确认就增加1个MSS。这会使得每过一个RTT,发送速率就翻倍。

        TCP发送速率起始慢,但在慢启动阶段以指数增长。

      • 慢启动结束阶段

        如果存在一个由超时指示的丢包事件(注意,不包括冗余指示的丢包),TCP发送方将cwnd设置为1并重新开始慢启动过程。同时还将第二个状态变量的值**ssthresh(慢启动阈值)**设置为 cwnd/2。

        当cwnd的值等于 ssthresh 时,结束慢启动并且TCP转移到拥塞避免模式。此时TCP会更为谨慎的增加 cwnd。

        如果检测到3个冗余ACK,则TCP执行快速重传并进入快速恢复状态。

    • 拥塞避免

      一旦进入拥塞避免状态,cwnd的值大约是上次遇到拥塞时的值的一半,此时采用一种较保守的方法:每个RTT只将cwnd的值增加一个MSS。

      注意区分开,慢启动初始时是每个报文段被确认则增加一个MSS。而这里是每个RTT增加一个MSS。

      对于冗余ACK指示的丢包事件来说,TCP将cwnd减半,并且当收到3个冗余ACK时,将ssthresh的值记录为cwnd的值的一半。

    • 快速恢复

      • 在快速恢复中,对于引进TCP进入快速恢复状态的缺失报文段,对收到的每个冗余ACK,cwnd的值增加一个MSS。最终当对丢失报文段的一个ACK到达时,TCP在降低cwnd后进入拥塞避免状态。
      • 如果出现超时事件,快速恢复在执行如同在慢启动和拥塞避免中相同的动作后,迁移到慢启动状态:当丢包事件出现时,cwnd的值被设置为1个MSS,并且ssthresh的值设置为 cwnd 值的一半。

    image-20210515131916271

  • 公平性

    TCP会在多条连接之间平等共享带宽,但UDP因为没有拥塞控制机制,因此UDP源有可能容易压制TCP流量。

  • 明确拥塞通告:网络辅助拥塞控制

    • 对于IP和TCP的扩展方案 RFC3168 允许网络明确向TCP发送方和接收方发出拥塞信号。这种形式的网络辅助拥塞控制称为明确拥塞通告(Explicit Congestion Notification, ECN),涉及到TCP和IP协议。
    • 在网络层,IP数据报首部的服务类型字段中的两个比特被用于ECN。路由器所使用的一种ECN比特设置表示该路由器正在历经阻塞。该阻塞标志则由被标记的IP数据报所携带,送给目的主机,再由目的主机通知发送主机
    • RFC3168 推荐仅当拥塞持续不断存在时才设置 ECN比特。发送主机所使用的另一种ECN比特设置通知路由器发送方和接收方是ECN使能的,因此能够对ECN指示的网络拥塞中采取行动。
    • 除了TCP以外的其他运输层协议也可以利用网络层发送ECN信号。
  • 版权声明: 本博客所有文章除特别声明外,著作权归作者所有。转载请注明出处!
  • Copyrights © 2020-2024 Kiprey
  • 访问人数: | 浏览次数:

请我喝杯咖啡吧~