《网络是怎样连接的》笔记

本文基于《网络是怎样连接的》该书做的笔记,有所删减

第 1 章 浏览器生成消息

1.1 生成 HTTP 请求消息

1.1.1 探索之旅从输入网址开始

我们的探索之旅从在浏览器中输入网址开始 ,在介绍浏览器的工作方式之前,让我们先来介绍一下网址。网址,准确来说应该叫 URL ,如果我说它就是以 http:// 开头的那一串东西,恐怕大家一下子就明白了,但实际上除了“http:”,网址还可以以其他一些文字开头,例如“ftp:”“file:”“mailto:” 等。

之所以有各种各样的 URL,是因为尽管我们通常是使用浏览器来访问Web 服务器的,但实际上浏览器并不只有这一个功能,它也可以用来在 FTP 服务器上下载和上传文件,同时也具备电子邮件客户端的功能。可以说,浏览器是一个具备多种客户端功能的综合性客户端软件,因此它需要一些东西来判断应该使用其中哪种功能来访问相应的数据,而各种不同的 URL 就是用来干这个的

例如在访问 Web 服务器和 FTP 服务器时,URL中会包含服务器的域名 和要访问的文件的路径名等,而发邮件的URL 则包含收件人的邮件地址。此外,根据需要,URL 中还会包含用户名、密码、服务器端口号 等信息。

请添加图片描述

1.1.2 浏览器先要解析 URL

浏览器要做的第一步工作就是对 URL 进行解析,从而生成发送给 Web服务器的请求消息。

在这里插入图片描述

1.1.3 省略文件名的情况

有时候我们也会见到一些不太一样的 URL,例如下面这个 URL 是以“/”来结尾的。

(a)http://www.lab.glasscom.com/dir/

像前面这样省略文件名时,服务器就会访问 /dir/index.html 或者 /dir/default.htm。

(c)http://www.lab.glasscom.com

当没有路径名时,就代表访问根目录下事先设置的默认文件 ,也就是 /index.html 或者 /default.htm

(d)http://www.lab.glasscom.com/whatisthis

whatisthis是文件还是文件夹,靠服务器去查找磁盘上这具体是什么来决定

1.1.4 HTTP 的基本思路

在这里插入图片描述

HTTP 协议定义了客户端和服务器之间交互的消息内容和步骤,其基本思路非常简单。首先,客户端会向服务器发送请求消息。请求消息中包含的内容是“对什么”和“进行怎样的操作”两个部分。

其中相当于“对什么”的部分称为 URI 。一般来说,URI 的内容是一个存放网页数据的文件名或者是一个 CGI 程序 的文件名。CGI 程序:对 Web 服务器程序调用其他程序的规则所做的定义就是 CGI,而按照 CGI 规范来工作的程序就称为 CGI 程序。

接下来“进行怎样的操作”的部分称为方法(也叫 HTTP 谓词,或者 HTTP 动词) 。方法表示需要让 Web 服务器完成怎样的工作

在这里插入图片描述

其中GET和POST最重要

收到请求消息之后,Web 服务器会根据这些要求来完成自己的工作,然后将结果存放在响应消息中。在响应消息的开头有一个状态码,它用来表示操作的执行结果是成功还是发生了错误。

当我们访问 Web 服务器时,遇到找不到的文件就会显示出 404 NotFound 的错误信息,其实这就是状态码。状态码后面就是头字段和网页数据。响应消息会被发送回客户端,客户端收到之后,浏览器会从消息中读出所需的数据并显示在屏幕上。

最常用的一个就是 GET 方法了。一般当我们访问 Web 服务器获取网页数据时,使用的就是 GET方法。

首先,在请求消息中写上 GET 方法,然后在 URI 中写上存放网页数据的文件名“/dir1/file1.html”,这就表示我们需要获取 /dir1/file1.html文件中的数据。当 Web 服务器收到消息后,会打开/dir1/file1.html 文件并读取出里面的数据,然后将读出的数据存放到响应消息中,并返回给客户端。最后,客户端浏览器会收到这些数据并显示在屏幕上。

还有一个经常使用的方法就是 POST。我们在表单(表单:网页中的文本框、复选框等能够输入数据的部分) 中填写数据并将其发送给 Web 服务器时就会使用这个方法。URI会指向 Web 服务器中运行的一个应用程序 的文件名,典型的例子包括“index.cgi”“index.php”等。

1.1.5 生成 HTTP 请求消息

对 URL 进行解析之后,浏览器确定了 Web 服务器和文件名,接下来就是根据这些信息来生成 HTTP 请求消息了。HTTP 消息在格式上是有严格规定的,因此浏览器会按照规定的格式来生成请求消息

在这里插入图片描述
在这里插入图片描述

准确来说,消息体的格式会通过消息头中的 Content-Type 字段来定义(MIME 类型)

在 HTML 源代码中会在表单的属性中指定使用哪种方法来发送请求,可能是 GET 也可能是 POST 。GET 方法能够发送的数据只有几百个字节,如果表单中的数据超过这一长度,则必须使用POST 方法来发送。

在这里插入图片描述

第二行开始为消息头。尽管通过第一行我们就可以大致理解请求的内容,但有些情况下还需要一些额外的详细信息,而消息头的功能就是用来存放这些信息。消息头的规格中定义了很多项目,如日期、客户端支持的数据类型、语言、压缩格式、客户端和服务器的软件名称和版本、数据有效期和最后更新时间等。

消息头中的内容随着浏览器类型、版本号、设置等的不同而不同,大多数情况下消息头的长度为几行到十几行不等。写完消息头之后,还需要添加一个完全没有内容的空行,然后写上需要发送的数据。这一部分称为消息体。
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

这里的 Challenge 指的是 Challenge-Response 身份验证模型中的一环。简单来说,Challenge 相当于“天王盖地虎”,Response 相当于“宝塔镇河妖”。

1.1.6 发送请求后会收到响应

响应消息的格式以及基本思路和请求消息是相同的,差别只在第一行上。在响应消息中,第一行的内容为状态码和响应短语,。状态码和响应短语表示的内容一致。状态码是一个数字,它主要用来向程序告知执行的结果;相对地,响应短语则是一段文字,用来向人们告知执行的结果。

状态码的第一位数字表示状态类型,第二、三位数字表示具体的情况

在这里插入图片描述

当网页中包含图片时,会在网页中的相应位置嵌入表示图片文件的标签 的控制信息。浏览器会在显示文字时搜索相应的标签,当遇到图片相关的标签时,会在屏幕上留出用来显示图片的空间,然后再次访问 Web 服务器,按照标签中指定的文件名向 Web 服务器请求获取相应的图片并显示在预留的空间中。

由于每条请求消息中只能写 1 个 URI,所以每次只能获取 1 个文件,如果需要获取多个文件,必须对每个文件单独发送 1 条请求。比如 1 个网页中包含 3 张图片,那么获取网页加上获取图片,一共需要向 Web 服务器发送 4 条请求。

1.2 向 DNS 服务器查询 Web 服务器的IP 地址

1.2.1 IP 地址的基本知识

互联网和公司内部的局域网都是基于 TCP/IP 的思路来设计的。

TCP/IP 的结构就是由一些小的子网,通过路由器 连接起来组成一个大的网络。

这里的子网可以理解为用集线器 连接起来的几台计算机 ,我们将它看作一个单位,称为子网。将子网通过路由器连接起来,就形成了一个网络 。

路由器:一种对包进行转发的设备。集线器:一种对包进行转发的设备,分为中继式集线器和交换式集线器两种。当计算机数量较少时,可以用一台集线器连接起来;当计算机数量较多时,一台集线器可能无法连接这么多计算机,可以增加集线器数量并将集线器相互连接起来,这时,凡是通过集线器连接起来的所有设备都属于同一个子网。

一些家用路由器中已经内置了集线器功能,因此大家可以理解为这种路由器内部同时包含路由器和集线器两种设备,它们在里面已经连接起来了。
在这里插入图片描述

在网络中,所有的设备都会被分配一个地址。这个地址即IP地址由分配给整个子网的网络号和分配给子网中的计算机的主机号组成。

发送者发出的消息首先经过子网中的集线器 ,转发到距离发送者最近的路由器上。接下来,路由器会根据消息的目的地判断下一个路由器的位置,然后将消息发送到下一个路由器,即消息再次经过子网内的集线器被转发到下一个路由器。不断重复,最终消息就被传送到了目的地。

让我们再来看一下实际的 IP 地址。实际的 IP地址是一串 32 比特的数字,按照 8 比特(1 字节)为一组分成 4组,分别用十进制表示然后再用圆点隔开。在 IP 地址的规则中,网络号和主机号连起来总共是 32 比特,但这两部分的具体结构是不固定的。在组建网络时,用户可以自行决定它们之间的分配关系,因此,我们还需要另外的附加信息来表示 IP 地址的内部结构。

在这里插入图片描述

这一附加信息称为子网掩码。子网掩码是一串与 IP 地址长度相同的 32 比特数字,其左边一半都是 1,右边一半都是 0。其中,子网掩码为 1 的部分表示网络号,子网掩码为 0的部分表示主机号。

将子网掩码按照和 IP 地址一样的方式以每 8 比特为单位用圆点分组后写在 IP 地址的右侧,这就是图 1.9(b)的方法。这种写法太长,我们也可以把 1 的部分的比特数用十进制表示并写在 IP 地址的右侧,如图 1.9(c) 所示。这两种方式只是写法上的区别,含义是完全一样的。

在这里插入图片描述

主机号部分的比特全部为 0 或者全部为 1 时代表两种特殊的含义。主机号部分全部为 0 代表整个子网。主机号部分全部为 1 代表向子网上所有设备发送包,即广播。

1.2.2 域名和 IP 地址并用的理由

原因:IP地址运行高效,但不利于人用,因此人用域名。

DNS(Domain Name System,域名服务系统)就是将IP与域名互相转换的机制。它还可以将邮件地址和邮件服务器进行关联,以及为各种信息关联相应的名称。

1.2.3 Socket 库提供查询 IP 地址的功能

对于 DNS 服务器,我们的计算机上一定有相应的 DNS 客户端,而相当于 DNS 客户端的部分称为DNS 解析器,或者简称解析器。

Socket 库其中包含的程序组件可以让其他的应用程序调用操作系统的网络功能 ,而解析器就是这个库中的其中一种程序组件。

Socket 库是在 UNIX 系操作系统 BSD 中开发的 C 语言库,互联网中所使用的大多数功能都是基于 Socket 库来开发的。因此,BSD 之外的其他操作系统以及 C 语言之外的其他编程语言也参照 Socket 库开发了相应的网络库。可以说,Socket 库是网络开发中的一种标准库。

1.2.4 通过解析器向 DNS 服务器发出查询

解析器的用法非常简单。Socket 库中的程序都是标准组件,只要从应用程序中进行调用就可以了。

在这里插入图片描述
只要运行这一行程序,我们也就完成了 IP 地址的查询。

根据域名查询 IP 地址时,浏览器会使用 Socket 库中的解析器。

1.2.5 解析器的内部原理

当控制流程转移到解析器后,解析器会生成要发送给 DNS 服务器的查询消息。这个过程与浏览器生成要发送给 Web 服务器的 HTTP 请求消息的过程类似,HTTP 消息是用文本编写的,但 DNS 消息是使用二进制数据编写的
在这里插入图片描述

发送消息这个操作并不是由解析器自身来执行,而是要委托给操作系统内部的协议栈 (操作系统内部的网络控制软件,也叫“协议驱动”“TCP/IP 驱动”等)来执行。然后通过网卡将消息发送给 DNS 服务器。

当 DNS 服务器收到查询消息后,它会根据消息中的查询内容进行查询。如果要访问的 Web 服务器已经在 DNS 服务器上注册,那么这条记录就能够被找到,然后其 IP 地址会被写入响应消息并返回给客户端。

向 DNS 服务器发送消息时,我们当然也需要知道 DNS 服务器的 IP 地址。只不过这个 IP 地址是作为 TCP/IP 的一个设置项目事先设置好的,不需要再去查询了。

1.3 全世界 DNS 服务器的大接力

1.3.1 DNS 服务器的基本工作

来自客户端的查询消息包含以下 3 种信息。

  1. 域名

    服务器、邮件服务器(邮件地址中 @ 后面的部分)的名称

  2. Class

    在最早设计 DNS 方案时,DNS 在互联网以外的其他网络中的应用也被考虑到了,而 Class 就是用来识别网络的信息。不过,如今除了互联网并没有其他的网络了,因此 Class 的值永远是代表互联网的IN

  3. 记录类型

    表示域名对应何种类型的记录。例如,当类型为 A 时,表示域名对应的是 IP 地址;当类型为 MX 时,表示域名对应的是邮件服务器。

在这里插入图片描述

Web 服务器的域名有很多都是像 www.lab.glasscom.com 这样以 www 开头的,但这并不是一定之规,只是因为最早设计 Web 的时候,很多 Web 服务器都采用了 www 这样的命名,后来就形成了一个惯例而已。

查询邮件服务器时会返回 优先级和 收件服务器域名这两条信息。当一个邮件地址对应多个邮件服务器时,需要根据优先级来判断哪个邮件服务器是优先的。优先级数值较小的邮件服务器代表更优先。之后再向DNS查询收件服务器域名

其他类型:根据 IP 地址反查域名的 PTR 类型,查询域名相关别名的CNAME 类型,查询 DNS 服务器 IP 地址的 NS 类型,以及查询域名属性信息的 SOA 类型等。

1.3.2 域名的层次结构

域名信息分布保存在多台 DNS 服务器中,这些 DNS 服务器相互接力配合,从而查找出要查询的信息。

每一个域都是用 . 来分割,一个DNS服务器可以存放一个或多个域的信息。且右边的域表示的层次越高。如www.baidu.com中com为顶级域名,baidu其次,www最低

1.3.3 寻找相应的 DNS 服务器并获取 IP 地址

一台DNS服务器中会储存下级域的ip地址,查询域名时是通过一个个DNS服务器爬取。com和cn就可以说是顶级域名了,但还有更上一级。根域一般用 . 来表示,如 www.bilibili.com. ,不过,一般都不写最后那个句点,因此根域的存在往往被忽略

但就我个人测试发现,有一些域名加上根域后会出现一些问题,但还有一些不会

分配给根域 DNS 服务器的 IP 地址在全世界仅有 13 个 ,根域 DNS 服务器在运营上使用多台服务器来对应一个 IP 地址,因此尽管 IP 地址只有13 个,但其实服务器的数量是很多的。

查询过程是客户端访问最近的DNS服务器S,DNS服务器S查找自己是否有该域名信息,没有就找根域DNS查找,根DNS查找后没有就把子域DNS服务器A的IP给S,让S去问A,A如果查找之后也没有,A就把子域DNS服务器B的IP给S,让S去问B,以此类推,最终找到 该域名的IP地址,最后返回给客户端。也就是S是去查找的中心,S直接和其他DNS打交道,其他DNS没有相互访问。最后把结果给用户

1.3.4 通过缓存加快 DNS 服务器的响应

DNS 服务器有一个缓存 功能,可以记住之前查询过的域名。如果要查询的域名和相关信息已经在缓存中,那么就可以直接返回响应。但当原本的注册信息可能会发生改变,这时缓存中的信息就有可能是不正确的。因此,DNS 服务器中保存的信息都设置有一个有效期,当缓存中的信息超过有效期后,数据就会从缓存中删除。

而且,在对查询进行响应时,DNS 服务器也会告知客户端这一响应的结果是来自缓存中还是来自负责管理该域名的 DNS 服务器。

1.4 委托协议栈发送消息

1.4.1 数据收发操作概览

要发送给Web 服务器的 HTTP 消息是一种数字信息(digital data),因此也可以说是委托协议栈来发送数字信息。

使用 Socket 库来收发数据的操作过程简单来说,收发数据的两台计算机之间连接了一条数据通道,数据沿着这条通道流动,最终到达目的地。

建立管道的关键在于管道两端的数据出入口(称为套接字)。我们需要先创建套接字,然后再将套接字连接起来形成管道。实际的过程是下面这样的。首先,服务器一方先创建套接字,然后等待客户端向该套接字连接管道 。当服务器进入等待状态时,客户端就可以连接管道了。

当数据全部发送完毕之后,连接的管道将会被断开。管道在连接时是由客户端发起的,但在断开时可以由客户端或服务器任意一方发起 。当管道断开后,套接字也会被删除。到此为止,通信操作就结束了。

综上所述,收发数据的操作可以大致总结为以下 4 个。

(1)创建套接字(创建套接字阶段)(2)将管道连接到服务器端的套接字上(连接阶段)(3)收发数据(通信阶段)(4)断开管道并删除套接字(断开阶段)

前面这 4 个操作都是由操作系统中的协议栈来执行的,浏览器等应用程序并不会自己去做连接管道、放入数据这些工作,而是委托协议栈来代劳。

这些委托的操作都是通过调用 Socket 库中的程序组件充当了一个桥梁的角色来执行的,最终会被原原本本地传递给协议栈。

1.4.2 创建套接字阶段

在这里插入图片描述

客户端创建套接字的操作非常简单,只要调用 Socket 库中的 socket 程序组件 就可以了

小写的 socket 表示程序组件的名称,大写字母开头的 Socket 表示库,而汉字的“套接字”则表示管道两端的接口。

套接字创建完成后,协议栈会返回一个描述符,描述符是用来识别不同的套接字的

1.4.3 连接阶段:把管道接上去

应用程序通过调用 Socket 库中的名为 connect 的程序组件来完成这一操作。这里的要点是当调用 connect 时,需要指定描述符、服务器 IP 地址和端口号这 3 个参数。当调用 connect 时,协议栈就会执行连接操作。当连接成功后,协议栈会将对方的 IP 地址和端口号等信息保存在套接字中,这样我们就可以开始收发数据了

服务器上所使用的端口号是根据应用的种类事先规定好的,仅此而已。比如 Web 是 80 号端口,电子邮件是 25号端口 。

客户端在创建套接字时,协议栈会为这个套接字随便分配一个端口号 。接下来,当协议栈执行连接操作时,会将这个随便分配的端口号通知给服务器。

描述符:应用程序用来识别自身套接字的机制

IP 地址和端口号:客户端和服务器之间用来识别对方套接字的机制

1.4.4 通信阶段:传递消息

发送信息:通过Socket库的write程序组件,指定描述符和数据,委托协议栈发送消息

接受消息:通过Socket库的read程序组件,指定描述符,委托协议栈接收消息,将收到的信息放在应用程序的接收缓冲区中

1.4.5 断开阶段:收发数据结束

我们可以调用 Socket 库的 close 程序组件进入断开阶段。最终,连接在套接字之间的管道会被断开,套接字本身也会被删除。

HTTP 协议规定,当 Web 服务器发送完响应消息之后,应该主动执行断开操作 ,因此 Web 服务器会首先调用 close 来断开连接。当浏览器调用 read 执行接收数据操作时,read 会告知浏览器收发数据操作已结束,连接已经断开。浏览器得知后,也会调用 close 进入断开阶段。

HTTP 协议将 HTML 文档和图片都作为单独的对象来处理,每获取一次数据,就要执行一次连接、发送请求消息、接收响应消息、断开的过程。

在 HTTP版本 1.1 中就可以能够在一次连接中收发多个请求和响应使用这种方法

第 2 章 用电信号传输 TCP/IP数据——探索协议栈和网卡

2.1 创建套接字

2.1.1 协议栈的内部结构

在这里插入图片描述

TCP/IP 软件采用分层结构上层会向下层逐层委派工作。

浏览器、邮件等一般应用程序收发数据时用 TCP;DNS 查询等收发较短的控制数据时用UDP。

传送数据时,数据会被切分成一个一个的网络包 ,而将网络包发送给通信对象的操作就是由 IP 来负责的。此外,IP 中还包括 ICMP 协议和 ARP 协议。

ICMP 用于告知网络包传送过程中产生的错误以及各种控制消息,ARP 用于根据 IP 地址查询相应的以太网 MAC 地址 。MAC 地址:符合 IEEE 规格的局域网设备都使用同一格式的地址,这种地址被称为 MAC 地址。

2.1.2 套接字的实体就是通信控制信息

套接字记录了用于控制通信操作的控制信息,例如通信对象的 IP 地址、端口号、通信操作的进行状态等。还会记录是否已经收到响应,以及发送数据后经过了多长时间,才能根据这些信息按照需要执行重发操作

协议栈是根据套接字中记录的控制信息来工作的。

在 Windows 中可以用 netstat 命令显示套接字内容 。图中每一行相当于一个套接字,当创建套接字时,就会在这里增加一行新的控制信息

在这里插入图片描述

其中本地 IP 地址和远程 IP 地址都是 0.0.0.0,这表示通信还没开始,IP 地址不确定 。PID:Process ID(进程标识符)的缩写

2.1.3 调用 socket 时的操作

应用程序调用socket 申请创建套接字,协议栈根据应用程序的申请执行创建套接字的操作。

创建套接字时,首先分配一个套接字所需的内存空间,然后向其中写入初始状态并将表示这个套接字的描述符告知应用程序。
在这里插入图片描述

2.2 连接服务器

2.2.1 连接是什么意思

创建套接字之后,应用程序就会调用 connect,随后协议栈会将本地的套接字与服务器的套接字进行连接。通信双方交换控制信息,在套接字中记录这些必要信息并准备数据收发的一连串操作

链接阶段做的事情如:将目的地的ip地址与端口等信息告诉协议栈,用户把自己的ip地址与端口告诉服务器。

准确的来讲将连接叫做准备更合适

2.2.2 负责保存控制信息的头部

通信操作中使用的控制信息分为两类。
(1) 头部中记录的信息(2) 套接字(协议栈中的内存空间)中记录的信息

控制信息有包头部,头部可以分为 TCP 头部、IP 头部以太网头部(又称“MAC 头部”) 。理解了头部各字段的含义,就等于理解了整个通信的过程

在这里插入图片描述
在这里插入图片描述

控制信息还会保存在套接字中,用来控制协议栈操作的信息 。应用程序传递来的信息以及从通信对象接收到的信息都会保存在这里,还有收发数据操作的执行状态等信息也会保存在这里

2.2.3 连接操作的实际过程

connect(< 描述符 >, < 服务器 IP 地址和端口号 >, …)

上面的调用提供了服务器的 IP 地址和端口号,这些信息会传递给协议栈中的 TCP 模块。

我们将头部中的控制位的 SYN 比特设置为 1,大家可以认为它表示连接 。

发送消息时:TCP模块附上TCP头之后给IP模块,IP模块附上IP头和以太网头之后给以太网模块。

连接操作时将信息进行上头后,发送消息。当找到对应的套接字之后,套接字中会写入相应的信息,并将状态改为正在连接 。上述操作完成后,服务器的 TCP 模块会返回响应,需要在 TCP 头部中设置发送方和接收方端口号以及 SYN 比特,和并将ACK 控制位设为 1 ,这表示已经接收到相应的网络包。

如果由于某些原因不接受连接,那么将不设置 SYN,而是将 RST 比特设置为 1。
客户端向服务器发送第一个网络包时,将 ACK比特设为 0。

然后,网络包就会返回到客户端,通过 IP 模块到达 TCP 模块,并通过 TCP 头部的信息确认连接服务器的操作是否成功。如果 SYN 为 1则表示连接成功,这时会向套接字中写入服务器的 IP 地址、端口号等信息,同时还会将状态改为连接完毕。

然后客户端也需要将 ACK 比特设置为 1 并发回服务器,连接操作才算全部完成。

2.3 收发数据

2.3.1 将 HTTP 请求消息交给协议栈

应用程序调用 write 将要发送的数据交给协议栈开始的,协议栈收到数据后执行发送操作。

协议栈会把传来的数据先放在缓冲区里,然后再一并发出去。通过最大容纳的数据和最大等待时间来判断。

MTU 表示一个网络包的最大长度,在以太网中一般是 1500 字节 。MTU 是包含头部的总长度,因此需要从 MTU 减去头部的长度,然后得到的长度就是一个网络包中所能容纳的最大数据长度,这一长度叫作 MSS 。当从应用程序收到的数据长度超过或者接近 MSS 时再发送出去,就可以避免发送大量小包的问题了。

MTU:Maximum Transmission Unit,最大传输单元。在使用 PPPoE 的 ADSL 等网络中,需要额外增加一些头部数据,因此 MTU 会小于 1500字节。

MSS:Maximum Segment Size,最大分段大小。 TCP 和 IP 的头部加起来一般是 40 字节,因此 MTU 减去这个长度就是 MSS。例如,在以太网中, MTU 为 1500,因此 MSS 就是 1460。TCP/IP 可以使用一些可选参数(protocol option),如加密等,这时头部的长度会增加

在这里插入图片描述

起始帧分界符:Start Frame Delimiter,SFD。

FCS:Frame Check Sequence,帧校验序列。

协议栈的内部有一个计时器,当经过一定时间之后,就会把网络包发送出去 。

应用程序在发送数据时可以指定一些选项,比如如果指定“不等待填满缓冲区直接发送”

2.3.2 对较大的数据进行拆分

发送应用程序的数据一般都比较大,因此 TCP 会按照网络包的大小对数据进行拆分。在这里插入图片描述

2.3.3 使用 ACK 号确认网络包已收到

首先,TCP 模块在拆分数据时,会先算好每一块数据相当于从头开始的第几个字节,将算好的字节数写在 TCP 头部中,“序号”字段就是派在这个用场上的。

接收方可以通过计算,知道发送的数据是从第几个字节开始,长度是多少了(MSS)。

在这里插入图片描述

有这些信息,接收方就能够检查收到的网络包有没有遗漏。

例如,假设上次接收到第 1460 字节,那么接下来如果收到序号为 1461 的包,说明中间没有遗漏

然后接收方会将到目前为止接收到的数据长度加起来,计算出一共已经收到了多少个字节,然后将这个数值写入 TCP 头部的 ACK 号中并将控制位中的 ACK 比特设为 1(这代表 ACK 号字段有效)发送给发送方 。

但实际的通信中,序号并不是从 1 开始的,初始值是随机值,这是因为如果序号都从 1 开始,通信过程就会非常容易预测

连接过程中,有一个将 SYN 控制位设为 1 并发送给服务器的操作,就是在这一步将序号的初始值告知对方的。实际上,在将 SYN 设为 1 的同时,还需要同时设置序号字段的值,而这里的值就代表序号的初始值 。

在这里插入图片描述

在得到对方确认之前,发送过的包都会保存在发送缓冲区中。如果对方没有返回某些包对应的 ACK 号,那么就重新发送这些包。如超时重传,丢失重传
网卡、集线器、路由器都没有错误补偿机制,一旦检测到错误就直接丢弃相应的包

如果 TCP 会在尝试几次重传无效之后强制结束通信,并向应用程序报错。
通过“序号”和“ACK 号”可以确认接收方是否收到了网络包。

2.3.4 根据网络包平均往返时间调整 ACK 号等待时间

TCP 采用了动态调整等待时间的方法,这个等待时间是根据 ACK 号返回所需的时间来判断的。等待时间有一个最小值,这个值在每个操作系统上不一样,基本上是在 0.5 秒到 1 秒之间。

2.3.5 使用窗口有效管理 ACK 号

在这里插入图片描述

每发送一个包就等待一个 ACK 号的方式浪费时间。因此有了滑动窗口,就是在发送一个包之后,不等待 ACK 号返回,而是直接发送后续的一系列包。

接收到的包放在协议栈的缓存区里,然后这些包会被拆包还原数据交给应用程序,但当处理不过来时,缓冲区被填满时就会溢出,后面的包就接收不到了。

滑动窗口方式的基本思路:接收方通过 TCP 头部中的窗口字段将自己能接收的数据量告知发送方,发送方再调整自己的发送速度

能够接收的最大数据量称为窗口大小 ,它是 TCP 调优参数中非常有名的一个。

2.3.6 ACK 与窗口的合并

更新窗口大小的时机应该是接收方从缓冲区中取出数据传递给应用程序的时候。

在等待发送 ACK 号的时候正好需要更新窗口,这时就可以把 ACK 号和窗口更新放在一个包里发送

当需要连续发送多个 ACK 号时,只发送最后一个 ACK号就可以了,中间的可以全部省略。窗口更新一样如此

2.4 从服务器断开并删除套接字

2.4.1 数据发送完毕后断开连接

应用程序会调用 Socket 库的 close 程序。然后协议栈会生成包含断开信息的 TCP 头部,将控制位中的 FIN 比特设为1。套接字中也会记录下断开操作的相关信息。接收方当收到 FIN 为 1 的 TCP 头部时,接收方的协议栈会将自己的套接字标记为进入断开操作状态。接收方会返回一个 ACK 号。

接收方应用程序调用read时会被告知已经断开,然后会调用 close 来结束数据收发操作,接收方的协议栈也会和服务器一样,生成一个FIN 比特为 1 的 TCP 包,然后委托 IP 模块发送给服务器。发送方就会返回 ACK 号。这时通信就全部结束了。

在这里插入图片描述

2.4.2 删除套接字

通信结束后套接字不会被马上删除,因为如果接收方的ACK号未发送成功,发送方会再发送一次FIN。而套接字被删除后,创建了新的套接字,新套接字碰巧又被分配了同一个端口号 ,而服务器重发的 FIN 正好到达,这时新套接字就开始执行断开操作了

客户端的端口号是从空闲的端口号中随意选择的,一般来说会等待几分钟之后再删除套接字

2.5 IP 与以太网的包收发操作

2.5.1 包的基本知识

在这里插入图片描述
在这里插入图片描述

网络中有路由器和集线器两种不同的转发设备,它们在传输网络包时有着各自的分工

(1)路由器根据目标地址判断下一个路由器的位置

(2)集线器在子网中将网络包传输到下一个路由

实际上,集线器是按照以太网规则传输包的设备,而路由器是按照 IP规则传输包的设备

(1)IP 协议根据目标地址判断下一个 IP 转发设备的位置

(2)子网中的以太网协议将包传输到下一个转发设备

IP 协议会查找下一个路由器的以太网地址(MAC 地址),并将这个地址写入MAC 头部中。这样一来,以太网协议就知道要将这个包发到哪一个路由器上了

在这里插入图片描述

集线器里有一张表(用于以太网协议的表),可根据以太网头部中记录的目的地信息查出相应的传输方向。接下来,包会到达下一个路由器。路由器中有一张 IP协议的表,可根据这张表以及 IP 头部中记录的目的地信息查出接下来应该发往哪个路由器。为了将包发到下一个路由器,我们还需要查出下一个路由器的 MAC 地址,并记录到 MAC 头部中,可以理解为改写了 MAC 头部 。

当使用除以太网之外的其他网络进行传输时,MAC 头部也会被替换为适合所选通信规格的其他头部。

2.5.2 包收发操作概览

凡是局域网所使用的头部都叫 MAC 头部,但其内容根据局域网的类型有所不同。此外,对于除局域网之外的其他通信技术,还有不同名称的各种头部,但它们只是名字不叫 MAC头部而已,承担的作用和 MAC 头部是相同的。

IP 模块负责添加如下两个头部。

(1)MAC 头部:以太网用的头部,包含 MAC 地址(2)IP 头部:IP 用的头部,包含 IP 地址

网卡会将网络包的数字信息转换为电信号或光信号,并通过网线(或光纤)发送出去,然后这些信号就会到达集线器、路由器等转发设备,再由转发设备一步一步地送达接收方。

接收的过程和发送的过程是相反的,信息先以电信号的形式从网线传输进来,然后由网卡将其转换为数字信息并传递给 IP 模块拆包传递给 TCP 模块,TCP模块再拆包出原始数据

无论要收发的包是控制包还是数据包,IP 对各种类型的包的收发操作都是相同的。

2.5.3 生成包含接收方 IP 地址的 IP 头部

在这里插入图片描述

发送方 IP 地址需要判断发送所使用的网卡,并填写该网卡的IP 地址。

可以通过route print 命令来显示路由表

在这里插入图片描述

路由表的第 1 行中,目标地址和子网掩码 都是 0.0.0.0,这表示默认网关,如果其他所有条目都无法匹配,就会自动匹配这一行 。如果 Gateway 和 Interface 列的 IP 地址相同,就表示不需要路由器进行转发,可以直接将包发给接收方的 IP 地址。

2.5.4 生成以太网用的 MAC 头部

在这里插入图片描述

以太网在判断网络包目的地时和 TCP/IP 的方式不同,因此必须采用相匹配的方式才能在以太网中将包发往目的地,而 MAC 头部就是干这个用的。

MAC 头部是以太网使用的头部,它包含了接收方和发送方的 MAC 地址等信息。

以太类型就表示后面内容的类型。以太网包的内容可以是 IP、ARP 等协议的包。

发送方 MAC 地址里填写网卡本身的 MAC 地址。MAC 地址是在网卡生产时写入 ROM 里的,只要将这个值读取出来写入 MAC 头部就可以了。

实际上,只有在操作系统启动过程中对网卡进行初始化的时候才会读取 MAC 地址,读取出来之后会存放在内存中,实际上使用的是内存中的值。读取MAC 地址的操作是由网卡驱动程序来完成的

我们还需要执行根据IP 地址查询 MAC 地址的操作。IP 模块根据路由表 Gateway 栏的内容判断应该把包发送给谁。

2.5.5 通过 ARP 查询目标路由器的 MAC 地址

在以太网中,有一种叫作广播的方法,可以把包发给连接在同一以太网中的所有设备。ARP就是利用广播对所有设备提问:“×× 这个 IP 地址是谁的?请把你的 MAC 地址告诉我。

ARP:Address Resolution Protocol,地址解析协议

如果对方无法作出 ARP 响应,这时只能认为对方不存在,包的发送操作就会失败。

我们会将查询结果放到一块叫作 ARP 缓存的内存空间中留着以后用。ARP 缓存中的值在经过一段时间后会被删除,一般这个时间在几分钟左右。

查询 MAC 地址需要使用 ARP

在这里插入图片描述
在这里插入图片描述

2.5.6 以太网的基本知识

在这里插入图片描述

以太网是一种为多台计算机能够彼此自由和廉价地相互通信而设计的通信技术,这种网络的本质其实就是一根网线。图上还有一种叫作收发器的小设备,它的功能只是将不同网线之间的信号连接起来而已。因此,当一台计算机发送信号时,信号就会通过网线流过整个网络,最终到达所有的设备。

通过 MAC 头部中的接收方 MAC 地址,就能够知道包是发给谁的;而通过发送方 MAC地址,就能够知道包是谁发出的;

以太网的基本结构这个原型后来变成了图(b)中的结构。这个结构是将主干网线替换成了一个中继式集线器 ,将收发器网线替换成了双绞线 。不过,虽然网络的结构有所变化,但信号会发送给所有设备这一基本性质并没有改变。中继式集线器:在以太网(10BASE-T/100BASE-TX)中简称集线器。

后来,图(c)这样的使用交换式集线器 的结构普及开来,现在我们说的以太网指的都是这样的结构。现在信号只会流到根据 MAC 地址指定的设备,而不会到达其他设备了。

将包发送到 MAC 头部的接收方 MAC 地址代表的目的地,用发送方MAC 地址识别发送方,用以太类型识别包的内容。具备这 3 个性质的网络就是以太网 。

无线局域网没有以太类型,但有具备同样功能的参数,可以认为它就是以太类型。因此,我们可以用无线局域网来代替以太网。

2.5.7 将 IP 包转换成电或光信号发送出去

在这里插入图片描述

网卡驱动程序通过网卡将数字信息转换为电或光信号,才能在网线上传输。

网卡的 ROM 中保存着全世界唯一的 MAC 地址,这是在生产网卡时写入的,将这个值读出之后就可以对 MAC 模块进行设置,MAC 模块就知道自己对应的 MAC 地址了。网卡中保存的 MAC 地址会由网卡驱动程序读取并分配给MAC模块。

2.5.8 给网络包再加 3 个控制数据

网卡驱动从 IP 模块获取包之后,会将其复制到网卡内的缓冲区中,然后向 MAC 模块发送发送包的命令。

MAC 模块会将包从缓冲区中取出,并在开头加上报头和起始帧分界符,在末尾加上用于检测错误的帧校验序列。

在这里插入图片描述

出于历史原因使用了“帧”而不是“包”,只是说法不同罢了。

报头是一串像 10101010…这样 1 和 0 交替出现的比特序列,长度为56 比特,它的作用是确定包的读取时机。当这些 1010 的比特序列被转换成电信号后,会形成如图这样的波形。

在这里插入图片描述

接收方在收到信号时,遇到这样的波形就可以判断读取数据的时机。

报头用来测定时机,SFD 用来确定帧的起始位置。

用电信号来表达数字信息时,我们需要让 0 和 1 两种比特分别对应特定的电压和电流

在这里插入图片描述

如果 1 和 0 连续出现的信号,由于电压和电流没有变化,我们就没办法判断出其中每个比特到底应该从哪里去切分。如果将时钟信号叠加进去,就可以判断出比特之间的界限了。当距离较远,时钟信号的传输会产生时间差,时钟就会发生偏移。

要解决这个问题,可以采用将数据信号和时钟信号叠加在一起的方法。由于时钟信号是按固定频率进行变化的,只要能够找到这个变化的周期,就可以从接收到的信号计算出原本的数据

只要对信号进行一段时间的观察,就可以找到其变化的周期。因此,我们在前面加上一段用来测量时钟信号的报头

起始帧分界符是一个用来表示包起始位置的标记。

末尾的 FCS(帧校验序列)用来检查包传输过程中因噪声导致的波形紊乱、数据错误,它是一串 32 比特的序列,是通过一个公式对包中从头到尾的所有内容进行计算而得出来的。当原始数据中某一个比特发生变化时,计算出来的结果就会发生变化。这样我们就可以判断出数据有没有错误。

2.5.9 向集线器发送网络包

发送信号的操作分为两种,一种是使用集线器的半双工模式,另一种是使用交换机的全双工 模式。发送和接收同时并行的方式叫作“全双工”,某一时刻只能进行发送或接收其中一种操作的叫作“半双工”。

在半双工模式中,为了避免信号碰撞,首先要判断网线中是否存在其他设备发送的信号。如果有,则需要等待该信号传输完毕,因为如果在有信号时再发送一组信号,两组信号就会发生碰撞。

发送信号时MAC 模块从报头开始将数字信息按每个比特转换成电信号,然后由 PHY,或者叫 MAU 的信号收发模块发送出去 。在这里,将数字信息转换为电信号的速率就是网络的传输速率,例如每秒将 10 Mbit 的数字信息转换为电信号发送出去,则速率就是 10Mbit/s。

根据以太网信号方式的不同,有些地方叫 MAU(Medium Attachment Unit,介质连接单元),有些地方叫 PHY(Physical Layer Device,物理层装置)。在速率为 100 Mbit/s以上的以太网中都叫 PHY。

网卡的 MAC 模块生成通用信号,然后由PHY(MAU)模块转换成可在网线中传输的格式,并通过网线发送出去。它还需要监控接收线路中有没有信号进来。

如果有其他设备同时发送信号,这些信号就会通过接收线路传进来。在使用集线器的半双工模式中,一旦发生这种情况,两组信号就会相互叠加,无法彼此区分出来,这就是所谓的信号碰撞。此时发送操作会终止。为了通知其他设备当前线路已发生碰撞,还会发送一段时间的阻塞信号 ,然后所有的发送操作会全部停止。等待一段时间之后,网络中的设备会尝试重新发送信号。

还必须让等待的时间相互错开。等待时间是根据 MAC 地址生成一个随机数计算出来的。

当网络拥塞时,发生碰撞的可能性就会提高,重试发送的时候可能又会和另外一台设备的发送操作冲突,这时会将等待时间延长一倍,然后再次重试。最多重试 10 次,如果还是不行就报告通信错误。

在全双工模式中,发送和接收可以同时进行,不会发生碰撞。

2.5.10 接收返回包

以太网的包接收操作和发送一样,和设备类型、TCP 的工作阶段以及应用程序的种类无关。操作类似,只不过是反向的

如果包末尾的 FCS校验错误,这个包就会被当作错误包而被丢弃。

在收到包后需要网卡主动去通知cpu,通知计算机的操作会使用一个叫作中断的机制。首先,网卡向扩展总线中的中
断信号线发送信号,该信号线通过计算机中的中断控制器连接到CPU。当产生中断信号时,CPU 会暂时挂起正在处理的任务,切换到操作系统中的中断处理程序 。然后,中断处理程序会调用网卡驱动,控制网卡执行相应的接收操作。

中断是有编号的,网卡在安装的时候就在硬件中设置了中断号,在中断处理程序中则将硬件的中断号和相应的驱动程序绑定。

2.5.11 将服务器的响应包从 IP 传递给 TCP

服务器的操作系统具备和路由器相同的包转发功能,可以像路由器一样对包进行转发。

如果IP模块收到的不是自己的包,IP 模块会通过 ICMP 消息将错误告知发送方

在这里插入图片描述
在这里插入图片描述

2.6 UDP 协议的收发操作

2.6.1 不需要重发的数据用 UDP 发送更高效

向 DNS 服务器查询 IP 地址的时候我们用的是 UDP协议。

UDP高效,不可靠,适合发小包

2.6.2 控制用的短数据

UDP协议在收发数据之前也不需要交换控制信息,也就是说不需要建立和断开连接的步骤,只要在从应用程序获取的数据前面加上 UDP 头部,然后交给 IP 进行发送就可以了

UDP 只负责单纯地发送包而已,遇到错误或者丢包也一概不管

在这里插入图片描述

UDP 可发送的数据最大长度为 IP 包的最大长度减去 IP 头部和 UDP 头部的长度。IP 包的最大长度是由 IP 头部中的“全长”字段决定的。“全长”字段的长度为 16 比特,因此最大长度为 65535 字节,再减去 IP 头部和 UDP 头部的长度,因此UDP 的最大数据长度为 65 507 字节。但太大了需要让 IP 模块使用分片功能拆分之后再传输。

2.6.3 音频和视频数据

还有另一个场景会使用 UDP,就是发送音频和视频数据的时候。音频和视频数据必须在规定的时间内送达,一旦送达晚了,就会错过播放时机,导致声音和图像卡顿。一旦错过播放时机,重发数据也是没有用的,因为声音和图像已经卡顿了,这是无法挽回的。当然,我们可以用高速线路让重发的数据能够在规定的时间内送达,但这样一来可能要增加几倍的带宽才行 。UDP 经常会被防火墙阻止,因此当需要穿越防火墙传输音频和视频数据时,尽管需要消耗额外的带宽,但有时候也只能使用 TCP。此外,音频和视频数据中缺少了某些包并不会产生严重的问题,只是会产生一些失真或者卡顿而已,一般都是可以接受的 。

第 3 章 从网线到网络设备——探索集线器、交换机和路由器

3.1 信号在网线和集线器中传输

3.1.1 每个包都是独立传输的

在这里插入图片描述

家用路由器已经集成了集线器和交换机的功能,但我们这里将所有功能独立出来,逐个来进行探索。

3.1.2 防止网线中的信号衰减很重要

网卡中的 PHY(MAU) 模块负责将包转换成电信号,信号通过 RJ-45 接口进入双绞线,以太网信号的本质是正负变化的电压,可以认为网卡的 PHY(MAU)模块就是一个从正负两个信号端子输出信号的电路。

PHY(MAU):以太网有多重派生方式,每种方式中信号收发模块的名称都不一样。现在100 Mbit/s 以上的以太网中叫作 PHY(物理层装置),以前低速方式中则叫作 MAU(介质连接单元)。
在这里插入图片描述

网线长度再加上噪声影响,在传输过程信号就会衰减,波形也会失真,导致接收方难以读取,还可能会出现对 0 和 1 的误判

电信号的频率越高,能量的损失率越大,衰减越严重

3.1.3 “双绞”是为了抑制噪声

“双绞”的意思就是以两根信号线为一组缠绕在一起,这种拧麻花一样的设计是为了抑制噪声的影响。

产生噪声的原因是网线周围的电磁波,当电磁波接触到金属等导体时,在其中就会产生电流。由于信号本身也是一种带有电压变化的电流,所以信号和噪声(感应电流)的电流就会混杂在一起,导致信号的波形发生失真

影响网线的电磁波分为外源和内源两种。

当外源电磁波接触到信号线时,会沿电磁波传播的右旋方向产生电流,这种电流会导致波形发生失真。如果我们将信号线缠绕在一起,信号线就变成了螺旋形,其中两根信号线中产生的噪声电流方向就会相反,从而使得噪声电流相互抵消,噪声就得到了抑制。

在这里插入图片描述

内源的噪声称为串扰(crosstalk)。这种噪声的强度其实并不高,但问题是噪声源的距离太近了。这些电磁波还没怎么衰减就已经接触到了相邻的信号线。关键在于双绞线的缠绕方式。在一根网线中,每一对信号线的扭绞间隔(节距)都有一定的差异,这使得在某些地方正信号线距离近,另一些地方则是负信号线距离近。就会相互抵消

(a)通过两根信号线的缠绕抵消外源性噪声;(b)通过改变节距抑制内源性噪声

除此之外还有其他一些工艺也能够帮助提升性能。例如在信号线之间加入隔板保持距离,以及在外面包裹可阻挡电磁波的金属屏蔽网等。

在这里插入图片描述
在这里插入图片描述

网线的性能是以“类”来区分的

3.1.4 集线器将信号发往所有线路

以太网的基本架构 就是将包发到所有的设备,然后由设备根据接收方 MAC 地址来判断应该接收哪些包,而集线器就是这一架构的忠实体现,它就是负责按照以太网的基本架构将信号广播出去。

集线器采用交叉接线的原因是将“发送线路”和“接收线路”连接起来

集线器的接口中有一个 MDI/MDI-X 切换开关, MDI 就是直连接线,负责发送,而 MDI-X 则是交叉接线,负责接收。由于集线器的接口一般都是 MDI-X模式,要将两台集线器相连时,就需要将其中一台改成 MDI 模式。

在这里插入图片描述

如果两台集线器所有的接口又都是 MDI-X 时,可以用交叉网线连接两台集线器。所谓交叉网线,就是一种将发送和接收信号线反过来接的网线。

在这里插入图片描述

两台计算机的网卡也可以相互连接。

中继电路的基本功能就是将输入的信号广播到集线器的所有端口上。有一些产品具有信号整形、错误抑制等功能,但基本上就是将输入的信号原封不动地输出到网线接口。

3.2 交换机的包转发操作

3.2.1 交换机根据地址表进行转发

在这里插入图片描述

MAC 模块将信号转换为数字信息,然后通过包末尾的FCS 校验错误,如果没有问题则存放到缓冲区中 。可以认为交换机的每个网线接口后面都是一块网卡。

交换机的端口不具有MAC 地址 。如果检测到错误就丢弃这个包。

换句话说,如果在计算机上安装多块网卡,并开启“混杂模式”让网卡接收所有的网络包,然后再安装一个和交换机具备同样功能的网络包转发软件,那么这台计算机就变成了一台交换机。

在这里插入图片描述

信号线排列成网格状,每一个交叉点都有一个交换开关,交换开关是电子控制的,通过切换开关的状态就可以改变信号的流向。交换电路的输入端和输出端分别连接各个接收端口和发送端口,网络包通过这个网格状的电路在端口之间流动。

举个例子,假设现在要将包从 2 号端口发送到 7 号端口,那么信号会从输入端的 2 号线进入交换电路,这时,如果让左起的 6 个开关水平导通,然后将第 7 个开关切换为垂直导通,信号就会像图上一样流到输出端 7 号线路

因此只要路径不重复,就可以同时传输多路信号。

3.3.2 MAC 地址表的维护

交换机在转发包的过程中,还需要对 MAC 地址表的内容进行维护,维护操作分为两种。第一种是收到包时,将发送方 MAC 地址以及其输入端口的号码写入MAC 地址表中。

另一种是删除地址表中某条记录的操作,这是为了防止设备移动时产生问题。地址表中的记录在一段时间不使用后就自动删除。

有时过时记录从地址表中删除之前,可能有发给该设备的包到达交换机。这时,交换机会将包转发到老的端口,通信就会发生错误

当地址表的内容出现异常时,只要重启一下交换机就可以重置地址表,也不需要手动进行维护。

3.2.3 特殊操作

在这里插入图片描述

交换机查询地址表之后发现记录中的目标端口和这个包的源端口是同一个端口。当交换机发现一个包要发回到原端口时,就会直接丢弃这个包。

地址表中找不到指定的 MAC 地址。将包转发到除了源端口之外的所有端口上,无论该设备连接在哪个端口上都能收到这个包。

如果接收方 MAC 地址是一个广播地址 ,那么交换机会将包发送到除源端口之外的所有端口。

广播地址(broadcast address)是一种特殊的地址,将广播地址设为接收方地址时,包会发送到网络中所有的设备。MAC 地址中的 FF:FF:FF:FF:FF:FF 和 IP 地址中的255.255.255.255 都是广播地址。

3.2.4 全双工模式可以同时进行发送和接收

全双工模式是交换机特有的工作模式,它可以同时进行发送和接收操作

使用双绞线时,发送和接收的信号线是各自独立的 ,因此在双绞线中信号不会发生碰撞。网线连接的另一端,即交换机端口和网卡的PHY(MAU)模块以及 MAC 模块,其内部发送和接收电路也是各自独立的,信号也不会发生碰撞。

1000BASE-T 规格的千兆以太网中,发送和接收信号线不是独立的,而是在同一条线上同时传输两个方向的信号,但 PHY(MAU)模块可以将发送和接收的信号进行分离,因此两者也不会发生碰撞。

如果不存在碰撞,也就不需要半双工模式中的碰撞处理机制了。也就是说,发送和接收可以同时进行。然而,以太网规范中规定了在网络中有信号时要等该信号结束后再发送信号。于是,人们对以太网规范进行了修订,增加了一个无论网络中有没有信号都可以发送信号的工作模式,同时规定在这一工作模式下停用碰撞检测。即全双工模式。

在这里插入图片描述

当网络在全双工模式下工作时检测信号碰撞的模块就失效了

3.2.5 自动协商:确定最优的传输速率

自动切换全双工和半双工模式的功能称为自动协商。相互连接的双方探测对方是否支持全双工模式和探测对方的传输速率并进行自动切换。

在以太网中,当没有数据在传输时,网络中会填充一种被称为连接脉冲的脉冲信号。从而能够检测对方是否在正常工作,或者说网线有没有正常连接。

以太网设备的网线接口周围有一个绿色的 LED指示灯,它表示是否检测到正常的脉冲信号。如果绿灯亮,说明PHY(MAU)模块以及网线连接正常 。MAC 模块、缓冲区、内存和总线部分的异常无法通过这个指示灯来判断。

在这里插入图片描述

后来,人们又设计出了这样的具有特定排列的脉冲信号,通过这种信号可以将自身的状态告知对方。

自动协商功能就利用了这样的脉冲信号,即通过这种信号将自己能够支持的工作模式 和传输速率相互告知对方,并从中选择一个最优的组合 。即是否支持全双工模式,以及是否支持半双工模式。

3.3 路由器的包转发操作

3.3.1 路由器的基本知识

网络包经过集线器和交换机之后,现在到达了路由器,并在此被转发到下一个路由器。这一步转发的工作原理和交换机类似,也是通过查表判断包转发的目标。

在这里插入图片描述

路由器转发模块和端口模块的关系,就相当于协议栈的 IP模块和网卡之间的关系。

转发模块会根据接收到的包的 IP 头部中记录的接收方 IP 地址,在路由表中进行查询,以此判断转发目标。

路由器的各个端口都具有 MAC 地址和 IP 地址。交换器不具有

3.3.2 路由表中的信息

在这里插入图片描述

路由器根据“IP 地址”判断转发目标。

路由器会忽略主机号,只匹配网络号(表中最左侧的)。

有时地址本身的子网掩码和路由表中的子网掩码是不一致的,这是路由聚合的结果。路由聚合会将几个子网合并成一个子网,并在路由表中只产生一条记录。

在这里插入图片描述

经过路由聚合,多个子网会被合并成一个子网,子网掩码会发生变化。

路由表的子网掩码列只表示在匹配网络包目标地址时需要对比的比特数量。

子网掩码的右边还有网关和接口两列,它们表示网络包的转发目标。根据目标地址和子网掩码匹配到某条记录后,路由器就会将网络包交给接口列中指定的网络接口(即端口) ,并转发到网关列中指定的 IP 地址。

跃点计数,它表示距离目标 IP 地址的距离是远还是近。这个数字越小,表示距离目的地越近;数字越大,表示距离目的地越远。

对路由表进行维护的方法有几种,大体上可分为以下两类。

(a)由人手动维护路由记录(b)根据路由协议机制,通过路由器之间的信息交换由路由器自行维护路由表的记录

其中(b)中提到的路由协议有很多种,例如 RIP、OSPC、BGP 等都属于路由协议。

3.3.3 路由器的包接收操作

和普通计算机的网卡操作一样

3.3.4 查询路由表确定输出端口

路由器会根据 MAC 头部后方的 IP 头部中的内容进行包的转发操作。首先是查询路由表判断转发目标。

通过路由器转发的网络包,其接收方 MAC 地址为路由器端口的MAC 地址。

根据包的接收方 IP 地址查询路由表中的目标地址栏,以找到相匹配的记录。有一规则称为“最长匹配”原则。当有不同IP的网络号都能匹配到时,优先去网络号最长的。

如目标地址192.168.1.0,其中192.168.1是网络号,现在有192.168和192.168.1两个记录,优先去192.168.1

有时候路由表中会存在网络号长度相同的多条记录,就需要根据跃点计数的值来进行判断。应选择跃点计数较小的记录。如果在路由表中无法找到匹配的记录,路由器会丢弃这个包,并通过ICMP 消息告知发送方 。

3.3.5 找不到匹配路由时选择默认路由

路由表中的最后一行的子网掩码为 0.0.0.0,关键就在这里,子网掩码 0.0.0.0 的意思是网络包接收方 IP 地址和路由表目标地址的匹配中需要匹配的比特数为 0,换句话说,就是根本不需要匹配。只要将子网掩码设置为 0.0.0.0,那么无论任何地址都能匹配到这一条记录,这样就不会发生不知道要转发到哪里的问题了。

只要在这一条记录的网关列中填写接入互联网的路由器地址,当匹配不到其他路由时 ,网络包就会被转发到互联网接入路由器。因此这条记录被称为默认路由,这一行配置的网关地址被称为默认网关。

在计算机的 TCP/IP 设置窗口中也有一个填写默认网关的框,意思是一样的。

路由表中子网掩码为 0.0.0.0 的记录表示“默认路由”。

3.3.6 包的有效期

转发前路由器要更新 IP 头部中的 TTL(Timeto Live,生存时间)字段。TTL 字段表示包的有效期,包每经过一个路由器的转发,这个值就会减 1,当这个值变成 0 时,就表示超过了有效期,这个包就会被丢弃。

发送方在发送包时会将 TTL 设为 64 或 128,现在的互联网即便访问一台位于地球另一侧的服务器,最多也只需要经过几十个路由器,因此只要包被正确转发,就可以在过期之前到达目的地。

3.3.7 通过分片功能拆分大网络包

路由器的端口种类多,不同种类的协议不一样,包的最大大小不一样,因此可能要使用 IP 协议中定义的分片功能对包拆分

分片操作:首先,我们需要知道输出端口的MTU ,看看这个包能不能不分片直接发送。最大包长度是由端口类型决定的,用这个最大长度减掉头部的长度就是 MTU,将 MTU 与要转发的包长度进行比较。如果输出端口的 MTU 足够大,那么就直接发送;如果输出端口的 MTU 太小,那么就需要将包按照这个 MTU进行分片,但在此之前还需要看一下 IP 头部中的标志字段,确认是否可以分片 。

一般来说都是可以分片的,但下面两种情况不能分片:1)发送方应用程序等设置了不允许分片;2)这个包已经是经过分片后的包

在这里插入图片描述

尽管 TCP 头部不是用户数据,但从 IP 协议的角度来看它也是数据的一部分。如果查询标志字段发现不能分片,那么就只能丢弃这个包,并通过ICMP 消息通知发送方。

数据被拆分后,每一份数据前面会加上 IP 头部,其大部分内容都和原本的 IP 头部一模一样

3.3.8 路由器的发送操作和计算机相同

如果路由表的网关列内容为 IP 地址,则该地址就是下一个转发目标。如果路由表的网关列内容为空,则 IP 头部中的接收方 IP地址就是下一个转发目标。

3.3.9 路由器与交换机的关系

路由器是基于 IP 设计的,而交换机是基于以太网设计的,因此 IP 与以太网的关系也就是路由器与交换机的关系。

换句话说,路由器将包的传输工作委托给交换机来进行 。当然,这里讲的内容只适用于原原本本实现 IP 和以太网机制的纯粹的路由器和交换机,实际的路由器有内置交换机功能的

除了使用交换机,还可以使用集线器,或者用交叉双绞线直接连接到路由器端口都可以。

IP(路由器)负责将包发送给通信对象这一整体过程,而其中将包传输到下一个路由器的过程则是由以太网(交换机)来负责的。

其他通信方式类似都是委托所使用的通信技术将包传输过去。IP 本身不负责包的传输,而是委托各种通信技术将包传输到下一个路由器

3.4 路由器的附加功能

3.4.1 通过地址转换有效利用 IP 地址

地址有限,所以有了内网,内网里的ip分配与其他的内网无关

规定某些地址是用于内网的,这些地址叫作私有地址,而原来的固定地址则叫作公有地址 。

在内网中可用作私有地址的范围仅限以下这些。

10.0.0.0 ~ 10.255.255.255

172.16.0.0 ~ 172.31.255.255

192.168.0.0 ~ 192.168.255.255

内网为了与互联网通信,内网分成两个部分,一部分是对互联网开放的服务器,另一部分是公司内部设备。

其中对互联网开放的部分分配公有地址,可以和互联网直接进行通信,这一部分和之前介绍的内容是一样的。相对地,内网部分则分配私有地址,内网中的设备不能和互联网直接收发网络包,而是通过地址转换进行连接。

在这里插入图片描述

3.4.2 地址转换的基本原理

地址转换的基本原理是在转发网络包时对 IP 头部中的 IP 地址和端口号 进行改写。

首先,TCP 连接操作的第一个包被转发到互联网时,将发送方 IP 地址从私有地址改写成公有地址。这里使用的公有地址是地址转换设备 的互联网接入端口的地址。与此同时,端口号也需要进行改写,地址转换设备会随机选择一个空闲的端口。然后,改写前的私有地址和端口号,以及改写后的公有地址和端口号,会作为一组相对应的记录保存在地址转换设备内部的一张表中。

在这里插入图片描述

在对外只能使用一个公有地址的情况下,可以用不同的端口号来区别内网中的不同终端。改写发送方 IP 地址和端口号之后,包就被发往互联网,最终到达服务器,然后服务器会返回一个包。服务器返回的包的接收包是原始包的发送方,因此返回的包的接收方就是改写后的公有地址和端口号。然后再将其反转成原始地址

访问互联网的操作全部完成后,对应表中的记录就会被删除。

3.4.3 改写端口号的原因

现在我们使用的地址转换机制是同时改写地址和端口号的,但早期的地址转换机制是只改写地址,不改写端口号的。用这种方法也可以让公司内网和互联网进行通信,而且这种方法更简单。但是,使用这种方法的前提是私有地址和公有地址必须一一对应,也就是说,有多少台设备要上互联网,就需要多少个公有地址。

因此如果用公有地址加上端口的组合对应一个私有地址,一个公有地址就可以对应几万个私有地址,这种方法提高了公有地址的利用率。

3.4.4 从互联网访问内网

对于从内网访问互联网的包,即便其发送方私有地址和端口号没有保存在对应表中也是可以正常转发的,因为用来改写的公有地址就是地址转换设备自身的地址,而端口号只要随便选一个空闲的端口就可以了,这些都可以由地址转换设备自行判断。

然而,对于从互联网访问公司内网的包,如果在对应表中没有记录就无法正常转发。因为如果对应表中没有记录,就意味着地址转换设备无法判断公有地址与私有地址之间的对应关系。

没有在访问互联网的内网设备,是无法从互联网向其发送网络包的。

除非内网主动允许,否则是无法从互联网向公司内网发送网络包的。这种机制具有防止非法入侵的效果。

我们只要事先手动添加对应表里的记录就可以访问内网里的设备了。

3.4.5 路由器的包过滤功能

包过滤就是在对包进行转发时,根据 MAC 头部、IP 头部、TCP 头部的内容 ,按照事先设置好的规则决定是转发这个包,还是丢弃这个包。我们通常说的防火墙设备或软件,大多数都是利用这一机制来防止非法入侵的 。

也有些设备可以根据 TCP 头部后面的数据内容设置过滤规则,不过一般不太常见。也有一些防火墙是用其他机制来防止非法入侵的。

第 4 章 通过接入网进入互联网内部——探索接入网和网络运营商

4.1 ADSL 接入网的结构和工作方式

4.1.1 互联网的基本结构

在这里插入图片描述

距离的不同和路由的维护方式(自动维护),就是互联网与家庭、公司网络之间最主要的两个不同点。

4.1.2 连接用户与互联网的接入网

互联网接入路由器发送网络包的操作和以太网路由器有一点不同,互联网接入路由器是按照接入网规则来发送包的。

一般家用的接入网方式包括 ADSL 、FTTH 、CATV、电话线、ISDN 等,公司则还可能使用专线。

下面先介绍一个比较有代表性的例子——ADSL。接入网这个词表示的是通信线路的用法,而并不表示通信线路的结构。例如公司里使用的专线,当它用来连接互联网时就叫作接入网,而用来连接总公司和分公司时就不叫接入网。

ADSL:Asymmetric Digital Subscriber Line,不对称数字用户线。它是一种利用架设在电线杆上的金属电话线来进行高速通信的技术,它的上行方向(用户到互联网)和下行方向(互联网到用户)的通信速率是不对称的。

FTTH:Fiber To The Home,光纤到户。指的是将光纤接入家庭的意思。

4.1.3 ADSL Modem 将包拆分成信元

在这里插入图片描述

ADSL 技术使用的接入线路,其内部结构如图 所示。用户端路由器 发出的网络包通过 ADSLModem 和电话线到达电话局,然后到达 ADSL 的网络运营商(即ISP,互联网服务提供商)。

在这里插入图片描述

在网络包从用户传输到运营商的过程中,会变换几种不同的形态,有些情况下会使用集成了互联网接入路由器和 ADSL Modem 的多功能 ADSL Modem(也叫路由型 ADSL Modem),其实就是把路由器和 ADSL Modem 装到一个外壳里而已。中文全称为“调制解调器”

首先,客户端生成的网络包先经过集线器和交换机到达互联网接入路由器,并在此从以太网包中取出IP 包并判断转发目标。接下来,包发送的操作也很类似。如果互联网接入路由器和 ADSL Modem 之间是通过以太网连接的,发送信号本身的过程跟之前是一样的,但以太网的头部会有一些差异。这部分的具体情况各运营商会有所不同,网络包会加上 MAC 头部、PPPoE 头部、PPP 头部总共 3 种头部,然后按照以太网规则转换成电信号后被发送出去 。

BAS:Broadband Access Server,宽带接入服务器。它也是一种路由器。PPP:Point-to-Point Protocol,点到点协议。它是电话线、ISDN 等通信线路所使用的一种协议,集成了用户认证、配置下发、数据压缩、加密等各种功能。这是后面将会讲到的 PPPoE 方式所规定的。

然后发送给ADSL Modem(PPPoE方式下)互联网接入路由器将包发送出去之后,包就到达了 ADSL Modem,然后,ADSL Modem 会把包拆分成很多小格子,每一个小格子称为一个信元。信元是一个非常小的数据块,开头是有 5 个字节的头部,后面是 48 个字节的数据,用于一种叫作ATM 的通信技术。

ATM:Asynchronous Transfer Mode,异步传输。它是在以电话线为载体的传统电话技术基础上扩展出来的一种通信方式。它的数据传输是以“信元”为单位来进行的,这和以包为单位传输数据的 TCP/IP 很像,但这种方式并不适用于计算机通信。

ADSL Modem 将包拆分成信元,并转换成电信号发送给分离器。

4.1.4 ADSL 将信元“调制”成信号

ADSL 采用的方法要复杂一些。其中有两个原因,一个原因是方波信号的波形容易失真,随着距离的延长错误率也会提高;另一个原因是方波信号覆盖了从低频到高频的宽广频段,信号频率越高,辐射出来的电磁噪声就越强,因此信号频谱太宽就难以控制噪声。

因此,ADSL Modem 采用了一种用圆滑波形(正弦波)对信号进行合成来表示 0 和 1 的技术,这种技术称为调制。调制有很多方式,ADSL采用的调制方式是振幅调制(ASK)和相位调制(PSK)相结合的正交振幅调制(QAM) 方式。

振幅调制是用信号的强弱,也就是信号振幅的大小来对应 0 和 1 的方式。振幅小的信号为 0,振幅大的信号为 1,这是一种最简单的对应关系。

在这里插入图片描述

在这个例子中,振幅大小只有两个级别,如果增加振幅变化的级别,就可以对应更多的比特。例如,如果将振幅增加到 4 个级别,则振幅从小到大可分别对应 00、01、10 和 11,这样就可以表示两个比特了。这样做可以将单位时间内传输的数据量加倍,也就能够提高速率。

另一个组成要素是相位调制,这是一种根据信号的相位来对应 0 和 1的方式,用角度来对应 0 和 1 的方式就叫作相位调制。相位调制也可以通过将角度划分为更细的级别来增加对应的比特数量,从而提高速率。

将两种方式组合起来,正交振幅调制就可以用一个波表示更多的比特,从而提高传输速率。

4.1.5 ADSL 通过使用多个波来提高速率

不同频率的波可以合成,也可以用滤波器从合成的波中分离出某个特定频率的波。因此,我们可以使用多个频率合成的波来传输信号,这样一来,能够表示的比特数就可以成倍提高了。ADSL 就是利用了这一性质,通过多个波增加能表示的比特数来提高速率的。

在这里插入图片描述

ADSL 使用间隔为 4.3125 kHz 的上百个不同频率的波进行合成,每个波都采用正交振幅调制,而且,根据噪声等条件的不同,每个波表示的比特数是可变的。也就是说,噪声小的频段可以给波分配更多的比特,噪声大的频段则给波分配较少的比特 ,一般情况下,一个波可表示几个比特到几十个比特。

上行方向(用户到互联网)和下行方向(互联网到用户)的传输速率是不同的,原因也在这里。如果上行使用 26 个频段,下行则可以使用 95 个或者 223 个频段,波的数量不同,导致了上下行速率不同。

当然,下行使用的频段较高,这些信号容易衰减而且更容易受到噪声的影响

ADSL 会持续检查线路质量,动态判断使用的频段数量,以及每个频段分配到的比特数。具体来说,当 Modem 通电后,会发送测试信号,并根据信号的接收情况判断使用的频段数量和每个频段的比特数,这个过程称为训练(握手),需要几秒到几十秒的时间。

4.1.6 分离器的作用

ADSL Modem 将信元转换为电信号之后,信号会进入一个叫作分离器的设备,然后 ADSL 信号会和电话的语音信号混合起来一起从电话线传输出去。

在信号从用户端发送出去时,电话和 ADSL 信号只是同时流到一条线路上而已,分离器实际上并没有做什么事。信号从电话线传入的时候。这时,分离器需要负责将电话和 ADSL 的信号进行分离。

在这里插入图片描述

分离器的功能是将一定频率以上的信号过滤掉,也就是过滤掉了 ADSL 使用的高频信号,这样一来,只有电话信号才会传入电话机,但对于另一头的 ADSLModem,则是传输原本的混合信号给它。

ADSL Modem 内部已经具备将ADSL 频率外的信号过滤掉的功能,因此不需要在分离器进行过滤。

实际上它还可以防止电话对 ADSL 产生干扰。如果没有分离器,拿起电话听筒接通电话的状态,和放下听筒挂断电话的状态下,信号的传输方式是不同的。当放下听筒时,电话机的电路和电话线是断开的,当拿起听筒时电话机就和电话线相连,电话机的信号就会传到电话线上。这两种状态的差异会导致噪声等线路状态的改变,如果 ADSL 通信过程中拿起话筒导致线路状态改变,就需要重新训练(握手),这就会导致几十秒的通信中断

4.1.7 从用户到电话局

从分离器出来,就是插电话线的接口,信号从这里出来之后,会通过室内电话线,然后到达大楼的 IDF 和 MDF ,外面的电话线在这里和大楼内部的室内电话线相连接。

如果是独栋住宅,就可以将室外线和室内线直接连起来。通过配线盘之后,信号会到达保安器。保安器是为了防止雷电等情况下电话线中产生过大电流的一种保护装置,内部有保险丝。

IDF:Intermediate Distribution Frame,中间配线盘。MDF:Main Distribution Frame,主配线盘(总配线架)。

[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-SLlT2QKX-1666349308289)(4f61cad63daf8972cac60e60382f973f.png)]

线越细衰减率越高

4.1.8 噪声的干扰

电话电缆中的信号也会受到噪声的干扰。此外,电话线原本的设计并没有考虑到传输 ADSL 这样的高频信号,从这个角度上可以说它比以太网双绞线更容易受到噪声的干扰

ADSL 信号受到干扰后并不会立即造成错误。ADSL 信号分布在多个频段上,只有和噪声频率相同的信号会受到影响而无法读取,即可用的信号数量减少,结果导致速率下降。

4.1.9 通过 DSLAM 到达 BAS

信号通过电话线到达电话局之后,会经过配线盘、分离器到达DSLAM。在这里,电信号会被还原成数字信息——信元。 DSLAM 通过读取信号波形,根据振幅和相位判断对应的比特值,将信号还原成数字信息,这一过程和用户端的 ADSLModem 在接收数据时的过程是一样的。

DSLAM:DSL Access Multiplexer,数字用户线接入复用设备。它是一种电话局用的多路ADSL Modem,可以理解为将多个 ADSL Modem 整合在一个外壳里的设备。

用户端 ADSL Modem 具备以太网接口,可以与用户端的路由器和计算机交互,收发以太网包,而 DSLAM 一般不用以太网接口,而是用 ATM接口,和后方路由器收发数据时使用的是原始网络包拆分后的 ATM 信元形式 。

也有一些 DSLAM 是不将网络包拆分成 ATM 信元的,而是直接以网络包的状态转换成ADSL 信号,这样的 DSLAM 在和后方路由器收发数据时也是使用包的形式。

信元从 DSLAM 出来之后,会到达一个叫作 BAS 的包转发设备。BAS 和 DSLAM 一样,都具有 ATM 接口,可以接收 ATM 信元,还可以将接收到的 ATM 信元还原成原始的包。它会将收到的包前面的MAC 头部和 PPPoE 头部丢弃,取出 PPP 头部以及后面的数据。MAC 头部和 PPPoE 头部的作用是将包送达 BAS 的接口,当接口完成接收工作后,它们就完成了使命,可以被丢弃了。

接下来,BAS 会在包的前面加上隧道专用头部 ,并发送到隧道的出口 。一般情况下使用的隧道技术为 L2TP,在这种情况下就会加上 L2TP 头部。然后,网络包会到达隧道出口的隧道专用路由器,在这里隧道头部会被去掉,IP 包会被取出,并被转发到互联网内部。

4.2.1 光纤的基本知识

另一种接入网技术FTTH是一种基于光纤的接入网技术。FTTH 的关键点在于对光纤的使用

在这里插入图片描述

光纤是由一种双层结构的纤维状透明材质(玻璃和塑料)构成的,通过在里面的纤芯中传导光信号来传输数字信息。光信号亮表示 1,暗表示 0。

在这里插入图片描述

这些光源就会根据信号电压的变化发光,高电压发光亮,低电压发光暗。光敏元件可以根据光的亮度产生不同的电压。

4.2.2 单模与多模光纤

纤芯的直径对光的传导影响很大,要理解这一点,我们得先来看看光在光纤中是如何传导的。首先,我们来看看光源发出的光是如何进入纤芯的。光源在所有方向上都会发光,因此会有各种角度的光线进入纤芯,但入射角度太大的光线会在纤芯和包层(纤芯外沿部分)的边界上折射出去,只有入射角较小的光线会被包层全反射,从而在纤芯中前进

在这里插入图片描述

当光线在纤芯和包层的边界上反射时,会由于反射角产生相位变化。当朝反射面前进的光线和被反射回来的光线交会时,如果两条光线的相位不一致,就会彼此发生干涉抵消,只有那些相位一致的光线才会继续在光纤中传导。

在这里插入图片描述

相位不同的波在干涉后会变弱、消失,最后就只剩下相位相同的波向周围扩散开来。

光在被纤芯和包层的边界反射时,相位会发生变化。这个变化的量随光在反射面的反射角度不同而不同,大多数角度下,都会因为相位不同而被干涉抵消。

不过,有几个特定的角度下,向反射面前进的光和反射回来的光的相位是一致的,只有以这些角度反射的光才能继续向前传导。只有少数按照特定角度入射以保持相位一致的光线才会继续传导。纤芯的直径也是根据这个角度来确定的,而且纤芯的直径大小会极大地改变光纤的性质。

在这里插入图片描述

根据纤芯直径,光纤可以划分成几种类型,大体上包括较细的单模光纤(8~10 μm)和较粗的多模光纤(50 μm 或 62.5 μm)。单模光纤的纤芯很细,只有入射角很小的光线才能进入,因此在能够保持相位一致的角度中,只有角度最小的光线能进入光纤。多模光纤的纤芯比较粗,入射角比较大的光也可以进入,这样一来,在相位一致的角度中,不仅角度最小的可以在光纤中传导,其他角度更大一些的也可以,单模和多模实际上表示相位一致的角度有一个还是多个。

在这里插入图片描述

多模光纤中可以传导多条光线,这意味着能通过的光线较多,对光源和光敏元件的性能要求也就较低,从而可以降低光源和光敏元件的价格。相对地,单模光纤的纤芯中只能传导一条光线,能通过的光线较少,相应地对于光源和光敏元件的性能要求就较高,但信号的失真会比较小。

信号失真与光在纤芯传导时反射的次数相关。多模光纤中,多条反射角不同的光线同时传导,其中反射角越大的光线反射次数越多,走过的距离也就越长;相对地,反射角越小的光线走过的距离越短。光通过的距离会影响其到达接收端的时间,也就是说,通过的距离越长,到达接收端的时间越长。结果,多条光线到达的时间不同,信号的宽度就会被拉伸,这就造成了失真。

在这里插入图片描述

单模光纤的失真小,可以比多模光纤更长,因此多模光纤主要用于一座建筑物里面的连接,单模光纤则用于距离较远的建筑物之间的连接。FTTH 属于后者,因此主要使用单模光纤。

4.2.3 通过光纤分路来降低成本

用光纤来代替 ADSL 将用户端接入路由器和运营商的 BAS 连接起来的接入方式就是 FTTH ,从形态上可大致分为两种。FTTH 和 ADSL 一样也有不同的衍生规格,主流规格是和 ADSL 一样采用 PPPoE 方式进行接入,后面我们的介绍也是基于 PPPoE 方式。2525一种是用一根光纤直接从用户端连接到最近的电话局。首先,用户端的光纤收发器 将以太网的电信号转换成光信号。这一步只进行电信号到光信号的转换,而不会像 ADSL 一样还需要将包拆分成信元,大家可以认为是将以太网包原原本本地转换成了光信号。接下来,光信号通过连接到光纤收发器的光纤直接到达 BAS 前面的多路光纤收发器。FTTH 一般使用单模光纤,因此其纤芯中只有特定角度的光信号能够反射并前进。然后,多路光纤收发器将光信号转换成电信号,BAS 的端口接收之后,将包转发到互联网内部。

将以太网的电信号转换成光信号的设备,也叫“终端盒”。

在这里插入图片描述

服务器收到后发出响应,响应包的光信号也是沿着同一条光纤传输到用户端的。通过上行和下行信号采用不同波长的光来区分服务器与客户端的信号。波长不同的光混合后可通过棱镜原理进行分离,因此光纤中的上行和下行信号即便混合起来也可以识别。像这样在一条光纤中使用不同的波长传输多个光信号的方式叫作波分复用。

接入网的结构另一种光纤的接入方式是在用户附近的电线杆上安装一个名为分光器的设备,通过这个设备让光纤分路,同时连接多个用户。在这种方式下,用户端不使用光纤收发器,而是使用一个叫作 ONU 的设备,它将以太网的电信号转换成光信号之后,会到达 BAS 前面的一个叫作 OLT 的设备。因为多个用户同时收发网络包时信号会在分光器产生碰撞。因此, OLT 和 ONU 中具备通过调整信号收发时机来避免碰撞的功能。

OLT 会调整信号发送时机并向 ONU 下发指令,ONU 则根据 OLT 的指令来发送数据。反过来,当 BAS 端向用户发送数据时,分光器只需要将信号发给所有用户就可以了,这里并不会发生碰撞,但这样做会导致一个用户收到其他所有用户的信号,造成信息泄露的问题,因此需要在每个包前面加上用于识别 ONU 的信息,当 ONU 收到信号后,会接收发给自己的信号并将其转换成以太网信号。

通过光纤分路连接多个用户的光纤接入模式统称为 PON(Passive Optical Network,无源光网络),可分为 GE-PON、WDM-PON、B-PON、G-PON 等多种方式,现在大多使用最高速率为 1 Gbit/s 的 GE-PON 方式。

ONU:Optical Network Unit,光网络单元。它和光纤收发器一样,可以将电信号转换成光信号,除此之外还具有和电话局的 OLT 相互配合避免信号碰撞的功能。这个设备有时也被叫作终端盒,因此终端盒这个词本身是对光纤收发器和 ONU 等光纤终端设备的统称。

OLT:Optical Line Terminal,光线路终端。

使用 PPPoE来传输包时,其工作过程和刚才讲过的 ADSL 类似,由互联网接入路由器在 IP 头部前面加上 MAC头部、 PPPoE 头部和 PPP 头部,然后由光纤收发器或者 ONU 转换成光信号 ,并通过光纤到达 BAS 前面的多路光纤收发器和 OLT,最后被还原成电信号并到达 BAS。不使用信元,而是将以太网包原原本本地转换成光信号。

4.3 接入网中使用的 PPP 和隧道

4.3.1 用户认证和配置下发

电话局中有专门用来安装 BAS 的地方,运营商会将 BAS 安装在这个地方,DSLAM 等设备也是一样的。

互联网本来就是由很多台路由器相互连接组成的,因此原则上应该是将接入网连接到路由器上。随着接入网发展到 ADSL 和 FTTH,接入网连接的路由器也跟着演进,而这种进化型的路由器就叫作 BAS。

ADSL 和 FTTH 接入网中,都需要先输入用户名和密码 ,登录之后才能访问互联网,而 BAS 就是登录操作的窗口。BAS 使用 PPPoE 方式来实现这个功能 。PPPoE 是由传统电话拨号上网上使用的 PPP 协议发展而来的

PPPoE:Point-to-Point Protocol over Ethernet,以太网的点对点协议,PPPoE 是由传统电话拨号上网上使用的 PPP 协议发展而来的。也有一些运营商使用后面会提到的 PPPoA 方式。

在这里插入图片描述

在使用电话线或者 ISDN 拨号上网时,PPP 是如图这样工作的。首先,用户向运营商的接入点拨打电话,电话接通后输入用户名和密码进行登录操作。用户名和密码通过 RADIUS 协议从 RAS 发送到认证服务器,认证服务器校验这些信息是否正确。当确认无误后,认证服务器会返回 IP 地址等配置信息,并将这些信息下发给用户。用户的计算机根据这些信息配置 IP 地址等参数,完成TCP/ IP 收发网络包的准备工作,接下来就可以发送 TCP/IP 包了。

RADIUS:Remote Authentication Dial-in User Service,远程认证拨号用户服务。

RAS:Remote Access Server,远程访问服务器。

这个过程的重点在于下发 TCP/IP 配置信息的步骤。在接入互联网时,必须为计算机分配一个公有地址

4.3.2 在以太网上传输 PPP 消息

ADSL 和 FTTH 接入方式也需要为计算机分配公有地址才能上网,这一点和拨号上网是相同的。不过,ADSL 和 FTTH 中,用户和 BAS 之间是通过电缆或光纤固定连接在一起的,因此没有必要验证用户身份,所以实际上并不需要 PPP 的所有这些功能。

然而,通过用户名和密码登录的步骤可以根据用户名来切换不同的运营商,这很方便 。因此,接入运营商在 ADSL 和 FTTH 中一般也会使用 PPP 。通过输入用户名和密码,可以掌握是谁在访问互联网,从网络管理的角度来看,这对于运营商来说也是很方便的。

拨号上网的 PPP 是无法直接用于 ADSL 和 FTTH 的

传输 PPP 消息的思路和将 IP 包装入以太网包中传输是一样的。PPP协议中没有定义以太网中的报头和 FCS 等元素,要传输 PPP 消息,必须有另一个包含报头、FCS、信号格式等元素的“容器”,然后将 PPP 消息装在这个容器里才行。于是,在拨号接入中 PPP 借用了HDLC 协议作为容器

HDLC:High-level Data Link Control,高级数据联接控制。

在这里插入图片描述

ADSL 和 FTTH用以太网包代替 HDLC 来装载 PPP 协议。此外,以太网和 PPP 在设计上有所不同,为了弥补这些问题就重新设计了一个新的规格,这就是 PPPoE。

在这里插入图片描述

在这里插入图片描述

4.3.3 通过隧道将网络包发送给运营商

BAS 除了作为用户认证的窗口之外,还可以使用隧道方式来传输网络包。所谓隧道,就类似于套接字之间建立的 TCP 连接。

这种方式中,首先需要在网络上的两台隧道路由器 之间建立 TCP 连接,然后将连接两端的套接字当作是路由器的端口,并从这个端口来收发数据。换句话说,在路由器收发包时,是基于隧道的规则向隧道中放入或取出网络包

4.3.4 接入网的整体工作过程

接入网的工作从用户端的互联网接入路由器进行连接操作开始。首先,接入路由器中需要配置运营商分配的用户名和密码 。然后,接入路由器会根据 PPPoE 的发现机制来寻找 BAS。这一机制和 ARP一样是基于广播来实现的

互联网接入路由器通过 PPPoE 的发现机制查询 BAS 的 MAC 地址。进入用户认证和下发配置的阶段。这里的工作过程有点复杂,我们只说重点。第一个重点是用户名和密码如何发送给 BAS。

这里有两种方式,一种是将密码进行加密的 CHAP 方式,另一种是不加密的 PAP 方式,在互联网接入路由器的设置画面中可以选择。进行加密的 CHAP 方式显然安全性更高,一般也推荐使用这种方式

CHAP:Challenge Handshake Authentication Protocol,挑战握手认证协议。

PAP:Password Authentication Protocol,密码验证协议。

从 BAS 向认证服务器发送密码时使用 RADIUS 协议,无论用户拨入使用 CHAP 还是PAP,RADIUS 都是加密的。

在校验密码之后 BAS 如何向用户下发 TCP/IP 配置信息。这里下发的配置信息包括分配给上网设备的 IP 地址 、DNS 服务器的 IP 地址以及默认网关的 IP 地址。当使用路由器连接互联网时,路由器会根据这些信息配置自身的参数。这样一来,路由器的BAS 端的端口就有了公有地址 ,路由表中也配置好了默认网关

如果要发送的包的IP地址找不到,路由器会选择默认路由,并将这个包转发给默认路由的网关地址,也就是 BAS 下发的默认路由。

在这里插入图片描述

然后包会被加上头部信息,并设置相应的字段。第一个 MAC 头部中,接收方 MAC 地址填写通过 PPPoE 发现机制查询到的 BAS 的 MAC 地址,发送方 MAC地址填写互联网接入路由器的 BAS 端的端口的 MAC 地址,然后以太类型填写代表 PPPoE 的 8864(十六进制)。

接下来是 PPPoE 头部和PPP 头部,它们包含的字段如图所示,其中除了载荷长度之外,其他的值都是可以事先确定的。再往后的部分就是包含 IP 头部在内的原始网络包。可以说,这里的转发操作中基本上不需要根据头部中的信息进行判断,只要将事先准备好的头部加上去就可以了。

BAS 在收到用户路由器发送的网络包之后,会去掉 MAC 头部和PPPoE 头部,然后用隧道机制将包发送给网络运营商的路由器。

4.3.5 不分配 IP 地址的无编号端口

当采用一对一连接,也就是两台路由器的端口用一根线直接连起来的情况下,一端发送的包肯定会到达另一端,那么这种情况下就没有必要按照路由表查询默认网关来判断转发目标地址了。

一对一连接的端口可以不分配 IP 地址,这种方式称为无编号。

4.3.6 互联网接入路由器将私有地址转换成公有地址

BAS 会向用户端下发TCP/IP 的配置信息,如果将这些信息配置在计算机上,就相当于计算机拥有了公有地址,这种情况下不需要进行地址转换也可以访问互联网。

如果使用路由器来上网,BAS 下发的参数就会被配置在路由器上。计算机会被分配一个私有地址,计算机发送的包需要通过路由器进行地址转换然后再转发到互联网中。

4.3.7 除 PPPoE 之外的其他方式

使用 PPPoA 方式的 ADSL 接入网 。ADSL 使用PPPoE 方式时,是先将 PPP 消息装入以太网包中,然后再将以太网包拆分并装入信元,而 PPPoA 方式是直接将 PPP 消息装入信元。由于只是开头加不加 MAC 头部和 PPPoE 头部的区别,PPP消息本身是没有区别的,因此密码校验、下发 TCP/IP 配置参数、收发数据包等过程都是和 PPPoE 基本相同的。

PPPoA:Point-to-Point Protocol over ATM。PPPoA 不能用于 FTTH,因为 FTTH 不使用 AT~M 信元。

由于 PPPoA 没有 MAC 头部,所以 PPP 消息是无法通过以太网来传输的,这就意味着需要和 BAS 收发 PPP 消息的设备,也就是计算机和路由器,必须和 ADSL Modem 是一体的,否则 PPP 机制就无法工作了。

PPPoE 方式中,如图4.18 所示,需要添加 PPPoE 头部和 PPP 头部,这意味着 MTU 就相应变小了 ,这可能会降低网络的效率。而 PPPoA 不使用以太网包来传输 PPP 消息,因此不会发生 MTU 变小的问题。PPPoE 一般还会和隧道技术一起使用,这时还需要加上隧道头部,MTU 就更短了。

PPPoE 会降低网络效率,PPPoA 也有 ADSL Modem 和路由器无法分离的限制,这两个问题其实都是由 PPP 引起的。因此,有一些运营商不使用 PPP,他们使用 DHCP 协议从 BAS 向用户端下发 TCP/IP 配置信息。

DHCP:Dynamic Host Configuration Protocol,动态主机配置协议。

在这里插入图片描述

首先客户端请求配置信息,然后 DHCP 服务器下发配置信息,非常简单,不需要像 PPP那样需要多个步骤,也不需要验证用户名和密码。没有用户名和密码,就意味着无法通过用户名来切换运营商网络,但这种方式也有优势,它可以单纯地直接传输以太网包,不需要添加额外的 PPP 头部,因此不会占用 MTU。

采用 DHCP 的运营商使用的 ADSL Modem 也和 PPPoE、PPPoA方式不同,这种 ADSL Modem 不使用信元,而是直接将以太网包调制成 ADSL 信号,因此没有 ADSL Modem 和路由器无法分离的问题 。使用信元的 PPPoE 和 PPPoA 方式中,BAS 需要配备比较昂贵的 ATM 接口,因此不使用信元还可以控制成本。

4.4 网络运营商的内部

4.4.1 POP 和 NOC

互联网的实体并不是由一个组织运营管理的单一网络,而是由多个运营商网络相互连接组成的。ADSL、FTTH 等接入网是与用户签约的运营商设备相连的,这些设备称为 POP ,互联网的入口就位于这里。

POP:Point of Presense,中文一般叫作“接入点”。

在这里插入图片描述

网络包通过接入网之后,到达运营商 POP 的路由器。POP 中包括各种类型的路由器,路由器的基本工作方式是相同的,但根据其角色分成了不同的类型。

在这里插入图片描述

专线的路由器就是具有通信线路端口的一般路由器。专线不需要用户认证、配置下发等功能 ,因此用一般的路由器就可以了。电话、ISDN 等拨号方式的接入网,这里使用的路由器称为 RAS。拨号接入需要对用户拨电话的动作进行应答,而 RAS 就具备这样的功能。RAS 也具备身份认证和配置下发功能。再往下是 PPPoE 方式的 ADSL 和 FTTH。PPPoE 方式中,ADSL、FTTH 接入服务商会使用 BAS,运营商的路由器则与 BAS 相连。PPPoE 中的身份认证和配置下发操作由接入服务商的 BAS 来负责,运营商的路由器只负责对包进行转发,因此这里也是使用一般的路由器就可以了。

端口多且价格便宜的路由器适用于接入网。图中左侧的路由器需要配备转发性能和数据吞吐量高的路由器。

NOC 是运营商的核心设备,从 POP 传来的网络包都会集中到这里,并从这里被转发到离目的地更近的 POP,或者是转发到其他的运营商。这里也需要配备高性能的路由器。

NOC:Network Operation Center,网络运行中心。

NOC 和 POP 并没有非常严格的界定。NOC 里面也可以配备连接接入网的路由器,很多情况下是和 POP 共用的。从 IP 协议的传输过程来看,也没有对两者进行区分的必然性,因为无论是哪个路由器,其转发网络包的基本工作原理都是相同的。

4.4.2 室外通信线路的连接

POP 和 NOC 一般更多地使用光纤 。

4.5 跨越运营商的网络包

4.5.1 运营商之间的连接

如果最终目的地 Web 服务器和客户端是连接在同一个运营商中的,那么 POP 路由器的路由表中应该有相应的转发目标。运营商的路由器可以和其他路由器交换路由信息,从而自动更新自己的路由表,通过这一功能,路由信息就实现了自动化管理。于是,路由器根据路由表中的信息判断转发目标。经过几次转发之后,网络包就到达了 Web 服务器所在的 POP 的路由器,然后从这里被继续转发到 Web 服务器。

如果服务器的运营商和客户端的运营商不同,网络包需要先发到服务器所在的运营商,这些信息也可以在路由表中找到,这是因为运营商的路由器和其他运营商的路由器也在交换路由信息。这时网络包会被转发到对方运营商的路由器。总之,对于互联网内部的路由器来说,无论最终目的地是否属于同一家运营商,都可以从路由表中查到

4.5.2 运营商之间的路由信息交换

只要让相连的路由器告知路由信息就可以了。只要获得了对方的路由信息,就可以知道对方路由器连接的所有网络,将这些信息写入自己的路由表中,也就可以向那些网络发送包了。获得对方的路由信息之后,我们也需要将自身的路由信息告知对方。这样一来,对方也可以将发往我们所在子网的包转发过来。这个路由信息交换的过程是由路由器自动完成的,这里使用的机制称为BGP 。

BGP:Border Gateway Protocol,边界网关协议。

这种路由交换可分为两类。一类是将互联网中的路由全部告知对方。例如图 4.26 中,如果运营商 D 将互联网上所有路由都告知运营商 E,则运营商 E 不但可以访问运营商D,还可以访问运营商 D 后面的运营商 B、A 和 C。然后,通过运营商 D 就可以向所有的运营商发送包。像这样,通过运营商 D 来发送网络包的方式称为转接。

在这里插入图片描述

另一种类型是两个运营商之间仅将与各自网络相关的路由信息告知对方。这样,只有双方之间的网络可以互相收发网络包,这种方式称为非转接,也叫对等 。对等的英文是 peer,BGP 规格中将互相交换路由信息的节点都称为 peer,但 BGP 的peer 实际上包含了转接和非转接两种节点。

4.5.3 与公司网络中自动更新路由表机制的区别

路由器之间相互交换信息自动更新路由表的方式在公司网络中也会用到。公司中使用的方式是寻找与目的地之间的最短路由,并按照最短路由来转发包。当要访问美国时采用最短最短路由的方式,就可能都只走一个运营商,该运营商需要向其他运营商收取相应的费用,否则就成义务劳动了,如果使用最短路由的方式也就是说无法阻止那些没交费的运营商使用这条线路

互联网中采用一种能够阻止某些来源的网络包的机制。首先,互联网中可以指定路由交换的对象。公司中,路由信息是在所有路由器间平等交换的,但运营商之间的路由交换是在特定路由器间一对一进行的。这样一来,运营商就可以只将路由信息提供给那些交了费的运营商,那些没交费的运营商也就无法将网络包发送过来了。

其次,在判断路由时,该机制不仅可以判断是否是最短路由,当某个目的地有多条路由时,可以对每条路由设置优先级。

如果一个运营商走不过去,可以走另一个运营商,无论网络包要发送到什么地方,都会确保能够获取相应的路由信息。

4.5.4 IX 的必要性

有多个运营商需要连接时我们可以设置一个中心设备,通过连接到中心设备的方式来减少线路数量,这个中心设备就称为 IX。IX:Internet eXchange,中文一般叫作“互联网交换中心”。

4.5.5 运营商如何通过 IX 互相连接

IX 的核心是具有大量高速以太网 端口的二层交换机。大家可以认为 IX 的核心就是大型的、高速的交换机。

在这里插入图片描述

一种是从路由器延伸出一根通信线路并连接到 IX 交换机上,另一种是将通过路由器间接连到 IX 交换机上

路由器发送网络包时,先通过 ARP 查询下一个路由器的 MAC地址,然后将其写入 MAC 头部发送出去即可。只要填写了正确的 MAC地址,就可以向任何运营商的路由器发送包。

第 5 章 服务器端的局域网中有什么玄机

5.1 Web 服务器的部署地点

5.1.1 在公司里部署 Web 服务器

在这里插入图片描述

因此让服务器裸奔并不是一个稳妥的办法。因此,现在我们一般采用图 5.1(b)中的方式,即部署防火墙 。它只允许发往指定服务器的指定应用程序的网络包通过,从而屏蔽其他不允许通过的包。

5.1.2 将 Web 服务器部署在数据中心

Web服务器可以放在网络运营商等管理的数据中心里,或者直接租用运营商提供的服务器。数据中心是与运营商核心部分 NOC 直接连接的,或者是与运营商之间的枢纽 IX 直接连接的。将服务器部署在这里可以获得很高的访问速度

5.2 防火墙的结构和原理

5.2.1 主流的包过滤方式

出于性能、价格、易用性等因素,现在最为普及的是包过滤方式。防火墙可分为包过滤、应用层网关、电路层网关等几种方式。

5.2.2 如何设置包过滤的规则

网络包的头部包含了用于控制通信操作的控制信息,只要检查这些信息,就可以获得很多有用的内容。这些头部信息中,经常用于设置包过滤规则的字段如表 5.1 所示。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述

在这里插入图片描述

假设我们的网络如图 5.2 所示,将开放给外网的服务器和公司内网分开部署,Web 服务器所在的网络可以从外网直接访问。现在我们希望允许从互联网访问 Web 服务器,但禁止 Web 服务器访问互联网。假设现在出现了一些寄生在服务器中感染其他服务器的恶意软件,如果阻止 Web 服务器访问互联网,就可以防止其他服务器被感染。

包从互联网流向 Web 服务器,从互联网发送过来的包其起点是不确定的,但终点是 Web 服务器。允许起点(发送方 IP 地址)为任意,终点(接收方 IP 地址)为 Web 服务器 IP地址的包通过(图 5.2 中表的第 1 行)。如果可以确定发送方 IP地址,也可以将其加入规则收到包之后,Web 服务器需要通过确认应答机制 通知发送方数据已经正常收到,这需要 Web 服务器向互联网发送包。在 Web 服务器发往互联网的包中,我们可以将起点(发送方 IP 地址)为 Web 服务器地址的包设置为允许通过(图 5.2 中表的第 3 行)。

5.2.3 通过端口号限定应用程序

还可以通过端口号限定应用程序发包

当包的接收方 IP 地址为 Web 服务器地址,且接收方端口号为 80 时,允许这些包通过(图 5.2 中表的第 1行),或者当包的发送方 IP 地址为 Web 服务器地址,且发送方端口号为 80 时,允许这些包通过(图 5.2 中的表的第 3 行)。

5.2.4 通过控制位判断连接方向

Web 使用的 TCP 协议是双向收发网络包的,因此如果单纯地阻止从 Web 服务器发往互联网的包,则从互联网访问 Web 服务器的操作也会受到影响而无法进行。

这里就需要用到 TCP 头部中的控制位。TCP 在执行连接操作时需要收发3 个包 ,其中第一个包的 TCP 控制位中 SYN 为 1,而 ACK 为0。其他的包中这些值都不同,因此只要按照这个规则就能够过滤到TCP 连接的第一个包。这样设置之后,当然也不会收到对方返回的第二个响应包,TCP 连接操作就失败了。

这样web服务器就可以回复响应信息但又不发送其他信息

DNS 查询使用的是 UDP 协议,而 UDP 与 TCP 不同,它没有连接操作,因此无法像TCP 一样根据控制位来判断访问方向。所以,我们无法设置一个规则,只允许公司内部访问互联网上的 DNS 服务器,而阻止从互联网访问公司内部的 DNS 服务器。

如果是使用包过滤之外的其他方式的防火墙,有时候是可以判断 UDP 应用程序的访问方向的。

5.2.6 从外部无法访问公司内网

包过滤方式的防火墙不仅可以允许或者阻止网络包的通过,还具备地址转换功能 ,因此还需要进行相关的设置。

以起点和终点作为条件,根据需要设置是否需要进行地址转换。只需要设置是否允许地址转换就可以了,凡是接收方为私有地址的包,在经过互联网中的路由器时都会被丢弃。

可以在路由表中配置私有地址相关的路由,使得公司内网到公开区域的访问可以以私有地址的形式来进行,公司内网和公开区域之间传输的包不需要地址转换。

默认状态下是无法从互联网访问公司内网的,因此我们不需要再设置一条包过滤规则来阻止从互联网访问公司内网。

5.2.7 通过防火墙

当包到达防火墙时,会根据这些规则判断是允许通过还是阻止通过。如果判断结果为阻止,那么这个包会被丢弃并被记录下来 。通过分析这些包能够搞清楚入侵者使用的手法,从而帮助我们更好地防范非法入侵。

如果将内置包过滤功能的路由器用作防火墙,则在丢弃包时基本上不会留下记录,这是因为路由器的内存容量小,没有足够的空间用来记录日志。

如果规则不复杂,也不需要记录日志,那么用内置包过滤功能的普通路由器来充当防火墙也是可以的。

包过滤方式的防火墙可根据接收方 IP 地址、发送方 IP 地址、接收方端口号、发送方端口号、控制位等信息来判断是否允许某个包通过。

5.2.8 防火墙无法抵御的攻击

防火墙无法检查包里的具体数据,黑客可以通过这个机制攻击,如服务器可能收到特定的数据后就宕机了

这个问题的根源在于 Web 服务器程序的Bug,因此修复 Bug 防止宕机就是其中一种方法。

另一种方法就是在防火墙之外部署用来检查包的内容并阻止有害包的设备或软件 。

5.3 通过将请求平均分配给多台服务器来平衡负载

5.3.1 性能不足时需要负载均衡

当很多用户同时访问时,无论服务器的性能再好,仅靠一台服务器还是难以胜任的。在这种情况下,使用多台服务器来分担负载的方法更有效。这种架构统称为分布式架构

最简单的一种方法就是采用多台 Web 服务器,减少每台服务器的访问量。假设现在我们有 3 台服务器,那么每台服务器的访问量会减少到三分之一,负载也就减轻了。要采用这样的方法,必须有一个机制将客户端发送的请求分配到每台服务器上。具体的做法有很多种,最简单的一种是通过 DNS 服务器来分配。当访问服务器时,客户端需要先向 DNS 服务器查询服务器的 IP 地址,如果在 DNS 服务器中填写多个名称相同的记录,则每次查询时 DNS 服务器都会按顺序返回不同的 IP 地址。

这种方式称为轮询(round-robin),通过这种方式可以将访问平均分配给所有的服务器。但这种方式是有缺点的。假如多台 Web 服务器中有一台出现了故障,这时我们希望在返回 IP 地址时能够跳过故障的 Web 服务器,然而普通的 DNS 服务器并不能确认 Web 服务器是否正常工作,因此即便Web 服务器宕机了,它依然可能会返回这台服务器的 IP 地址 。如果浏览器在访问 DNS 服务器返回的第一个 IP 地址失败时,能够继续尝试第二个 IP地址,就可以回避这个问题了,最近的浏览器有很多都已经具备了这样的功能。

此外,轮询分配还可能会引发一些问题。在通过 CGI 等方式动态生成网页的情况下,有些操作是要跨多个页面的,如果这期间访问的服务器发生了变化,这个操作就可能无法继续。例如在购物网站中,可能会在第一个页面中输入地址和姓名,在第二个页面中输入信用卡号,这就属于刚才说的那种情况。

5.3.2 使用负载均衡器分配访问

为了避免出现前面的问题,可以使用一种叫作负载均衡器的设备。使用负载均衡器时,首先要用负载均衡器的 IP 地址代替 Web 服务器的实际地址注册到 DNS 服务器上。客户端会认为负载均衡器就是一台 Web 服务器,并向其发送请求,然后由负载均衡器来判断将请求转发给哪台 Web 服务器 。

在这里插入图片描述

关键点就是如何判断将请求转发给哪台 Web 服务器。转发请求消息使用的是“代理”机制,缓存服务器也使用这种机制。此外,有些负载均衡器中也内置缓存功能。负载均衡器和缓存服务器很相似,或者可以说它是由缓存服务器进一步发展而来的。

用于对多台 Web 服务器分配访问的负载均衡器判断条件有很多种,根据操作是否跨多个页面,判断条件也会有所不同。如果操作没有跨多个页面,则可以根据 Web 服务器的负载状况来进行判断。负载均衡器可以定期采集 Web 服务器的 CPU、内存使用率,并根据这些数据判断服务器的负载状况,也可以向 Web 服务器发送测试包,根据响应所需的时间来判断负载状况。

查询操作本身就会增加 Web 服务器的负载。因此也有一种方案是不去查询服务器的负载,而是根据事先设置的服务器性能指数,按比例来分配请求。无论如何,这些方法都能够避免负载集中在某一台服务器上。当操作跨多个页面时,则不考虑 Web 服务器的负载,而是必须将请求发送到同一台 Web 服务器上。

要实现这一点,关键在于我们必须要判断一个操作是否跨了多个页面。要判断请求之间的相关性,就必须在 Web 服务器一端保存相应的信息,这会增加服务器的负担。

那么在不知道请求之间的相关性时,能不能根据一系列请求的发送方IP 地址相同这一点来判断呢?也不行。如果使用了我们后面要讲的代理机制 ,所有请求的发送方 IP 地址都会变成代理服务器的 IP 地址,无法判断实际发送请求的客户端是哪个。

可以在发送表单数据时在里面加上用来表示关联的信息,或者是对 HTTP 规格进行扩展,在 HTTP 头部字段中加上用来判断相关性的信息 。这样,负载均衡器就可以通过这些信息来作出判断,将一系列相关的请求发送到同一台 Web 服务器,对于不相关的请求则发送到负载较低的服务器了。这种信息俗称 Cookie。

5.4 使用缓存服务器分担负载

5.4.1 如何使用缓存服务器

除了使用多台功能相同的 Web 服务器分担负载之外,还可以将整个系统按功能分成不同的服务器 ,如 Web 服务器、数据库服务器。

缓存服务器就是一种按功能来分担负载的方法。缓存服务器是一台通过代理机制对数据进行缓存的服务器。代理介于Web 服务器和客户端之间,具有对 Web 服务器访问进行中转的功能。

当进行中转时,它可以将 Web 服务器返回的数据保存在磁盘中,并可以代替 Web 服务器将磁盘中的数据返回给客户端。这种保存的数据称为缓存,缓存服务器指的也就是这样的功能。Web 服务器需要执行检查网址和访问权限,以及在页面上填充数据等内部操作过程,因此将页面数据返回客户端所需的时间较长。

缓存服务器只要将保存在磁盘上的数据读取出来发送给客户端就可以了,因此可以比 Web 服务器更快地返回数据。不过,如果在缓存了数据之后,Web 服务器更新了数据,那么缓存的数据就不能用了,此外,CGI 程序等产生的页面数据每次都不同,这些数据也无法缓存。

在来自客户端的访问中一部分访问可以无需经过 Web 服务器,而由缓存服务器直接处理。

5.4.2 缓存服务器通过更新时间管理内容

缓存服务器和负载均衡器一样,需要代替 Web 服务器被注册到 DNS 服务器中。缓存服务器会接收请求消息,这个接收操作和 Web 服务器相同,就是创建用来等待连接的套接字,当客户端进行连接时执行连接操作,然后接收客户端发送的请求消息。从客户端来看,缓存服务器就相当于 Web 服务器。

接下来,缓存服务器会检查请求消息的内容,看看请求的数据是否已经保存在缓存中。

在这里插入图片描述

在这里插入图片描述
在这里插入图片描述

如果缓存服务器没有该消息内容的记录会在 HTTP 头部字段中添加一个Via 字段,表示这个消息经过缓存服务器转发,然后将消息转发给Web 服务器。

在这个过程中,我们需要判断应该将请求消息转发给哪台 Web 服务器。如果只有一台 Web 服务器,那么情况比较简单,但一台缓存服务器对应多台 Web 服务器就没那么简单了,需要根据请求消息的内容来判断应该转发给哪台 Web服务器。

比较有代表性的是根据请求消息的 URI中的目录名来进行判断。请求不同的目录名就转发到不同的服务器,在这个过程中,缓存服务器会以客户端的身份向目标 Web 服务器发送请求消息。于是,缓存服务器会收到来自 Web 服务器的响应消息,接收消息的过程也是以客户端的身份来完成的。接下来,缓存服务器会在响应消息中加上 Via头部字段,它表示这个消息是经过缓存服务器中转的,然后缓存服务器会以 Web 服务器的身份向客户端发送响应消息。同时,缓存服务器会将响应消息保存到缓存中,并记录保存的时间。这种在客户端和 Web 服务器之间充当中间人的方式就是代理的基本原理。

当缓存服务器收到了已记录的请求,会添加一个 If-Modified-Since 头部字段并将请求转发给 Web 服务器,询问 Web 服务器用户请求的数据是否已经发生变化。然后,Web 服务器会根据 If-Modified-Since 的值与服务器上的页面数据的最后更新时间进行比较,如果在指定时间内数据没有变化一样的表示没有变化的响应消息。

接下来,返回消息到达缓存服务器,然后缓存服务器就会知道 Web 服务器上的数据和本地缓存中的数据是一样的,于是就会将缓存的数据返回给客户端。

当 Web 服务器上的数据有变化时,后面的过程和没有命中缓存的情况是一样的。Web 服务器会返回最新版本的数据,然后缓存服务器加上 Via 字段发送给客户端,同时将数据保存在缓存中。

5.4.3 最原始的代理——正向代理

还有一种方法是在客户端一侧部署缓存服务器。缓存服务器使用的代理机制最早就是放在客户端一侧的,这才是代理的原型,称为正向代理 (forward proxy)。

正向代理刚刚出现的时候,其目的之一就是缓存,这个目的和服务器端的缓存服务器相同。不过,当时的正向代理还有另外一个目的,那就是用来实现防火墙。

在这里插入图片描述

代理服务器会先接收来自客户端的请求消息,然后再转发到互联网中 ,这样就可以实现只允许通过必要的网络包了。这时,如果能够利用代理的缓存,那么效果就会更好,因为对于以前访问过的数据,可以直接从位于公司内网的代理服务器获得,这比通过低速线路访问互联网要快很多 。

代理(Proxy)本来的意思并不是“转发”消息,而是先把消息收下来,然后“伪装”成原始客户端向 Web 服务器发出访问请求。利用代理实现防火墙此外,由于代理在转发过程中可以查看请求的内容,所以可以根据内容判断是否允许访问。也就是说,通过代理可以禁止员工访问危险的网站,或者是与工作内容无关的网站。

在使用正向代理时,一般需要在浏览器的设置窗口中的“代理服务器”一栏中填写正向代理的 IP 地址,浏览器发送请求消息的过程也会发生相应的变化。在没有设置正向代理的情况下,浏览器会根据网址栏中输入的 http://… 字符串判断 Web 服务器的域名,并向其发送请求消息;当设置了正向代理时,浏览器会忽略网址栏的内容,直接将所有请求发送给正向代理。请求消息的内容也会有一些不同。

没有正向代理时,浏览器会从网址中提取出 Web 服务器域名后面的文件名或目录名,然后将其作为请求的 URI 进行发送;而有正向代理时,浏览器会在请求的 URI 字段中填写完整的http://… 网址。

5.4.4 正向代理的改良版——反向代理

我们可以对正向代理进行改良,使得不需要在浏览器中设置代理也可以使用。也就是说,我们可以通过将请求消息中的 URI 中的目录名与 Web 服务器进行关联,使得代理能够转发一般的不包含完整网址的请求消息。我们前面介绍的服务器端的缓存服务器采用的正是这种方式,这种方式称为反向代理(reverse proxy)。

5.4.5 透明代理

缓存服务器判断转发目标的方法还有一种,那就是查看请求消息的包头部。因为包的 IP 头部中包含接收方 IP 地址,只要知道了这个地址,就知道用户要访问哪台服务器了 。这种方法称为透明代理(transparent proxy)。

HTTP 1.1 版本增加了一个用于表示访问目标 Web 服务器的 Host 字段,因此也可以通过 Host 字段来判断转发目标。这种方法也可以转发一般的请求消息,因此不需要像正向代理一样设置浏览器参数,也不需要在缓存服务器上设置转发目标,可以将请求转发给任意 Web 服务器。透明代理集合了正向代理和反向代理的优点,是一个非常方便的方式。

由于透明代理不需要设置在浏览器中,那么浏览器还是照常向 Web 服务器发送请求消息。反向代理采用的是通过 DNS 服务器解析引导的方法,但透明代理是不能采用这种方法的,否则透明代理本身就变成了访问目标,也就无法通过接收方 IP 地址判断转发目标了,这就失去了透明代理的意义。

总之,正常情况下,请求消息是从浏览器直接发送到 Web 服务器,并不会到达透明代理。于是,我们必须将透明代理放在请求消息从浏览器传输到 Web 服务器的路径中,当消息经过时进行拦截。如果请求消息有多条路径可以到达 Web 服务器,那么就必须在这些路径上都放置透明代理,因此一般是将网络设计成只有一条路可以走的结构,然后在这一条路径上放置透明代理。连接互联网的接入网就是这样一个关口,因此可以在接入网的入口处放置反向代理 。使用透明代理时,用户不会察觉到代理的存在,也不会注意到 HTTP 消息是如何被转发的,因此大家更倾向于将透明代理说成是缓存 。

5.5 内容分发服务

5.5.1 利用内容分发服务分担负载

缓存服务器部署在服务器端还是客户端,其效果是有差别的。

在这里插入图片描述

将缓存服务器放在客户端让网络流量更稳定,客户端的缓存服务器是归客户端网络运营管理者所有的,Web服务器的运营者无法控制它。

Web 服务器运营者和网络运营商签约,将可以自己控制的缓存服务器放在客户端的运营商处。这样一来,我们可以把缓存服务器部署在距离用户很近的地方,同时Web 服务器运营者还可以控制这些服务器

但这样部署数量太大了,非常不现实。我们可以筛选出一些主要的运营商,这样可以减少缓存服务器的数量。

作为一个 Web 服务器运营者,如果自己和这些运营商签约并部署缓存服务器,无论是费用还是精力都是吃不消的。为了解决这个问题,一些专门从事相关服务的厂商出现了,他们来部署缓存服务器,并租借给 Web 服务器运营者。这种服务称为内容分发服务 。

内容分发服务也叫 CDS(Content Delivery Service)。现在更常用的名称叫CDN(Content Delivery Network 或 Content Distribution Network)

提供这种服务的厂商称为 CDSP ,他们会与主要的供应商签约,并部署很多台缓存服务器 。

这样一来,每个网站运营者的平均成本就降低了,从而减少了网站运营者的负担。而且,和运营商之间的签约工作也由 CDSP 统一负责,网站运营者也节省了精力。

5.5.2 如何找到最近的缓存服务器

我们可以在 DNS 服务器返回 Web 服务器 IP 地址时,对返回的内容进行一些加工,使其能够返回距离客户端最近的缓存服务器的 IP 地址。

在这里插入图片描述

首先,作为准备,需要事先从缓存服务器部署地点的路由器收集路由信息。如图,一共有 4 台缓存服务器,在这 4 台服务器的部署地点又分别有 4 台路由器,则我们需要分别获取这 4 台路由器的路由表,并将 4 张路由表集中到 DNS 服务器上。接下来,DNS 服务器根据路由表查询从本机到 DNS 查询消息的发送方,也就是客户端 DNS 服务器的路由信息。

通过互联网内部的路由表中的路由信息可以知道先通过运营商 X,然后通过运营商 Y,最后到达运营商 Z 这样的信息,通过这样的信息可以大致估算出距离。依次查询所有路由器的路由表之后,我们就可以通过比较找出哪一台路由器距离客户端 DNS 服务器最近。

实际上,客户端DNS 服务器不一定和客户端在同一位置,因此可能无法得出准确的距离,但依然可以达到相当的精度。

5.5.3 通过重定向服务器分配访问目标

重定向:HTTP 规格中定义了很多头部字段,其中有一个叫作 Location 的字段。当 Web 服务器数据转移到其他服务器时可以使用这个字段,它的意思是“您要访问的数据在另一台服务器上,请访问那台服务器吧。

通过这种方法也可以将访问目标分配到最近的缓存服务器。当使用重定向告知客户端最近的缓存服务器时,首先需要将重定向服务器注册到 Web 服务器端的 DNS 服务器上。这样一来,客户端会将HTTP 请求消息发送到重定向服务器上。重定向服务器和刚才一种方法中的 DNS 服务器一样,收集了来自各个路由器的路由信息,并根据这些信息找到最近的缓存服务器,然后将缓存服务器的地址放到Location 字段中返回响应。这样,客户端就会重新去访问指定的缓存服务器了

在这里插入图片描述

使用重定向时 HTTP 消息的内容这种方法的缺点在于增加了 HTTP 消息的交互次数,相应的开销也比较大,但它也有优点。对 DNS 服务器进行扩展的方法是估算客户端DNS 服务器到缓存服务器之间的距离,因此精度较差;相对而言,重定向的方法是根据客户端发送来的 HTTP 消息的发送方 IP 地址来估算距离的,因此精度较高。

重定向服务器不仅可以返回带有 Location 字段的 HTTP消息,也可以返回一个通过网络包往返时间估算到缓存服务器的距离的脚本,通过在客户端运行脚本来找到最优的缓存服务器。这个脚本可以向不同的缓存服务器发送测试包并计算往返时间,然后将请求发送到往返时间最短的一台缓存服务器,这样就可以判断出对于客户端最优的缓存服务器,并让客户端去访问该服务器。

5.5.4 缓存的更新方法会影响性能

还有一个因素会影响缓存服务器的效率,那就是缓存内容的更新方法。缓存本来的思路是将曾经访问过的数据保存下来,然后当再次访问时拿出来用,以提高访问操作的效率。不过,这种方法对于第一次访问是无效的,而且后面的每次访问都需要向原始服务器查询数据有没有发生变化,如果遇到网络拥塞,就会使响应时间恶化。

要改善这一点,有一种方法是让 Web 服务器在原始数据发生更新时,立即通知缓存服务器,使得缓存服务器上的数据一直保持最新状态,这样就不需要每次确认原始数据是否有变化了,而且从第一次访问就可以发挥缓存的效果。

内容分发服务采用的缓存服务器就具备这样的功能。此外,除了事先编写好内容的静态页面之外,还有一些在收到请求后由 CGI 程序生成的动态页面,这种动态页面是不能保存在缓存服务器上的。

这种情况下,我们可以不保存整个页面,而是将应用程序生成的部分,也就是每次内容都会发生变化的动态部分,与内容不会发生变化的静态部分分开,只将静态部分保存在缓存中。Web 服务器前面存在着各种各样的服务器,如防火墙、代理服务器、缓存服务器等。请求消息最终会通过这些服务器,到达 Web 服务器。Web 服务器接收请求之后,会查询其中的内容,并根据请求生成并返回响应消息。

第 6 章 请求到达 Web 服务器,响应返回浏览器——短短几秒的“漫长旅程”迎来终点

6.1 服务器概览

6.1.1 客户端与服务器的区别

服务器可以分为很多种类,其硬件和操作系统与客户端是有所不同的 。但是,网络相关的部分,如网卡、协议栈、Socket 库等功能和客户端却并无二致。无论硬件和 OS 如何变化,TCP 和 IP 的功能都是一样的,或者说这些功能规格都是统一的 。

客户端计算机也可以调用用来等待连接的程序零件,服务器程序在客户端计算机上也可以运行。

6.1.2 服务器程序的结构

服务器需要同时和多个客户端通信,但一个程序来处理多个客户端的请求是很难的,因为服务器必须把握每一个客户端的操作状态 。一般的做法是,每有一个客户端连接进来,就启动一个新的服务器程序,确保服务器程序和客户端是一对一的状态。仅用一个程序来处理多个客户端请求的服务器程序也是存在的,只不过这种程序编写起来难度较高。

在这里插入图片描述

我们将程序分成两个模块,即等待连接模块和负责与客户端通信的模块 。当服务器程序启动并读取配置文件完成初始化操作后,就会运行等待连接模块。这个模块会创建套接字,然后进入等待连接的暂停状态。接下来,当客户端连发起连接时,这个模块会恢复运行并接受连接,然后启动客户端通信模块,并移交完成连接的套接字。接下来,客户端通信模块(b)就会使用已连接的套接字与客户端进行通信,通信结束后,这个模块就退出了。

通过这样的方式,可以降低程序编写的难度。服务器操作系统具有多任务 、多线程 功能,可以同时运行多个程序 ,服务器程序的设计正是利用了这一功能。

当然,这种方法在每次客户端发起连接时都需要启动新的程序,这个过程比较耗时,可以事先启动几个客户端通信模块,当客户端发起连接时,从空闲的模块中挑选一个出来将套接字移交给它来处理。

6.1.3 服务器端的套接字和端口号

在数据收发层面不需要区分客户端和服务器,而是能够以左右对称的方式自由发送数据。TCP 也正是在这样的背景下设计出来的。不过,连接这个操作是在有一方等待连接的情况下,另一方才能发起连接。因此,只有这个部分必须区分发起连接和等待连接这两个不同的角色。

从数据收发的角度来看,这就是客户端与服务器的区别,也就是说,发起连接的一方是客户端,等待连接的一方是服务器。这个区别体现在如何调用 Socket 库上。首先,客户端的数据收发需要经过下面 4 个阶段。

(1)创建套接字(创建套接字阶段)

(2)用管道连接服务器端的套接字(连接阶段)

(3)收发数据(收发阶段)

(4)断开管道并删除套接字(断开阶段)

相对地,服务器是将阶段(2)改成了等待连接和接受连接

在这里插入图片描述

在客户端发起连接的操作中,需要指定服务器端的端口号。具体的编号是根据服务器程序的种类,按照规则来确定的,例如 Web 服务器使用 80 号端口 。Socket 库和协议栈其实并不受到这个规则的制约,它们只负责向套接字写入 bind 所指定的端口号,并等待来自该端口的连接。

因此,我们也可以让 Web 服务器工作在 80 号之外的其他端口上。只不过,在这种情况下,客户端必须在 TCP 头部中指定这个端口号才能够完成连接。设置好端口号之后,协议栈会调用 listen 向套接字写入等待连接状态这一控制信息。这样一来,套接字就会开始等待来自客户端的连接网络包。然后,协议栈会调用 accept 来接受连接。

在这里插入图片描述

下来,协议栈会给等待连接的套接字复制一个副本,然后将连接对象等控制信息写入新的套接字中。到这里,我们就创建了一个新的套接字,并和客户端套接字连接在一起了。当 accept 结束之后,等待连接的过程也就结束了,这时等待连接模块会启动客户端通信模块,然后将连接好的新套接字转交给客户端通信模块

创建新套接字时端口号也是一个关键点。端口号是用来识别套接字的,因此我们以前说不同的套接字应该对应不同的端口号,但新创建的套接字副本必须和原来的等待连接的套接字具有相同的端口号。

但是这样一来又会引发另一个问题。端口号是用来识别套接字的,如果一个端口号对应多个套接字,就无法通过端口号来定位到某一个套接字了。当客户端的包到达时,如果协议栈只看 TCP 头部中的接收方端口号,是无法判断这个包到底应该交给哪个套接字的。

即要确定某个套接字时,不仅使用服务器端套接字对应的端口号,还同时使用客户端的端口号再加上IP 地址,总共使用下面 4 种信息来进行判断。

客户端之间的端口号是可以重复的。因此,我们还必须加上客户端的 IP 地址才能进行判断。

使用描述符来指代套接字的原因如下。

(1)等待连接的套接字中没有客户端 IP 地址和端口号

(2)使用描述符这一种信息比较简单

6.3 Web 服务器程序解释请求消息并作出响应

6.3.2 运行 CGI 程序

当需要 Web 服务器运行程序时,浏览器发送的 HTTP 请求消息内容会和访问 HTML 文档时不太一样

一般来说浏览器会将需要程序处理的数据放在 HTTP 请求消息中发送给服务器。这些数据有很多种类,例如购物网站订单表中的品名、数量、发货地址等,搜索引擎中输入的关键字也是一个常见的例子。

收到请求消息之后Web 服务器会检查 URI 指定的文件名,看一看这个文件是不是一个程序。这里的判断方法是在 Web 服务器中事先设置好的,一般是通过文件的扩展名来进行判断,例如将 .cgi、.php 等扩展名的文件设置为程序

如果判断要访问的文件为程序文件,Web 服务器会委托操作系统运行这个程序,然后从请求消息中取出数据并交给运行的程序 。如果方法为 GET,则将 URI 后面的参数传递给程序;如果方法为 POST,则将消息体中的数据传递给程序

输出数据的内容是由运行的程序生成的,然后交给Web 服务器,可能会进行一定的改造,然后web服务器返回响应信息

6.3.3 Web 服务器的访问控制

可以通过查询客户端的IP地址的域名,再通过域名查询IP地址,看看是否相符,可以避免注册假域名的攻击方式

6.4 浏览器接收响应消息并显示内容

6.4.1 通过响应的数据类型判断其中的内容

根据响应消息开头的 Content-Type 头部字段的值来进行判断数据类型

在这里插入图片描述
在这里插入图片描述

//还可以这样指定编码格式
Content-Type: text/html; charset=utf-8

我们可以检查文件的扩展名,如果为 .html 或 .htm 则看作是 HTML 文件,或者也可以检查数据的内容,如果是以 开头的则看作是 HTML 文档。不仅是 HTML 这样的文本文件,图片也是一样。图片是经过压缩的二进制数据,但其开头也有表示内容格式的信息,我们可以根据这些信息来判断数据的类型。

全局概览

在这里插入图片描述
在这里插入图片描述

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值