网络知识-《网络是怎样连接的》一书学习
Star Sea

整理《网络是怎样连接的》一书的知识要点,对整个网络有个大概的了解。
在开始之前我想在本书中找到部分常被问到的问题的答案:

  1. 从输入网址到页面加载出来发生了什么?
  2. 网络分层,和各分层的作用?
  3. TCP、UDP协议?

    概要

    image.png

    概念整理

    名称 含义
    接入网 互联网的入口线路称为接入网。一般来说,我们可以用电话线、ISDN、ADSL、有线电视、光线、专线等多种通信线路来接入互联网,这些通信线路统称为接入网
    接入点(Point of Presence, PoP) 接入点的实体是一台专为运营商设计的路由器,接入点的后面就是互联网的骨干部分了。网络包首先通过接入网被发送到接入点,然后再从这里被发送到全国甚至全世界
    套接字 套接字只是一个概念。在协议栈内部有一块用于存放控制信息的内存空间,这里记录了用于控制通信操作的控制信息,例如通信对象的IP地址、端口号、通信操作的进行状态等。这些控制信息可以说是套接字的实体。
    MTU 一个网络包的最大长度,以太网中一般为1500字节。
    MSS 一个网络包的最大长度,以太网中一般为1500字节。
    窗口大小 TCP缓存区能接收的最大数据量,决定了数据传输滑动窗口的并发传输的上限
    终端节点 包的发送方和接收方都称为终端节点,中间的转发设备称为转发节点或中间节点
    网卡的作用 实现数字信号和电信号之间的相互转化
    ARP Address Resolution Protocol,地址解析协议。查询IP对应的MAC地址,查询方法是广播,对同一子网的所有设备进行广播来获取MAC地址
    路由表 记录网络包地址和对应转发路由器地址以及发送包的网络接口的表,IP模块使用改表来获取目标地址IP组装包的IP头,可以通过route print命令来显示路由表
    以太网 3个性质:将包发送到MAC头部的接收方MAC地址代表的目的地,用发送方MAC地址识别发送方,用以太类型识别包的内容
    传输速率 将数字信号转化为电信号的速率,例如每秒将10Mbit的数字信息转换为电信号发送出去,则速率就是10 Mbit/s
    PHY(MAU) Physical Layer Device(物理层装置)(100 Mbit/s以上称为PHY)、Medium Attachment Unit(介质连接单元),其作用是对MAC模块产生的信号(电信号)进行格式转换,转化成可以在网线上传输的格式。此外,监控接收线路中有没有信号进来也是其作用。在半双工模式下(集线器)发送和接收不能同时进行,否则会产生信号碰撞,在全双工模式下(交换机)发送和接收可以同时进行
    ICMP Internet Control Message Protocol,Internet控制报文协议。当包传输过程中发生错误,用来发送控制消息
    FCS FCS(帧校验序列)用来检查包传输过程中因噪声导致的波形紊乱、数据错误
    SFD 起始帧分界符,用来确定帧的起始位置
    接入网 指连接互联网与家庭、公司网络的通信线路。一般家用的接入网方式包括ADSL、FTTH、CATV、电话线、ISDN等,公司则还可能使用专线
    BAS Broadband Access Server,宽带接入服务器,也是一种路由器。
    PPP Point-to-Point Protocol,点到点协议。它是电话线、ISDN等通信线路所使用的一种协议,集成了用户认证、配置下发、数据压缩、加密等各种功能。
    ATM Asynchronous Transfer Mode,异步传输。它是在以电话线为载体的传统电话技术基础上扩展出来的一种通信方式。它的数据传输是以“信元”为单位来进行的,这和以包为单位传输数据的TCP/IP很像,但这种方式并不适用于计算机通信。
    DSLAM DSL Access Multiplexer,数字用户线接入复用设备。它是一种电话局用的多路ADSL Modem,可以理解为将多个ADSL Modem整合在一个外壳里的设备。
    ONU Optical Network Unit,光网络单元。它和光纤收发器一样,可以将电信号转换成光信号,除此之外还具有和电话局的OLT相互配合避免信号碰撞的功能。这个设备有时也被叫做终端盒,因此终端盒这个词本身是对光纤收发器和ONU等光纤终端设备的统称。
    OLT Optical Line Terminal,光线路终端。

网络流程

浏览器生成消息

生成HTTP请求消息

浏览器先解析URL,根据HTTP协议的要求生成对应格式请求信息。web服务器会根据请求信息返回对应的响应信息。
请求信息:请求行(方法、URI、HTTP版本)、消息头(请求头)、消息体(请求携带的数据,例如post请求的表单数据等)
响应消息:状态行(HTTP版本、状态码、响应短语)、消息头(响应头)、消息体(具体响应的数据)
此处需要补充的是常见的消息头、以及缓存相关的消息头设置

DNS解析

  1. IP的基本知识

以下两图可以了解到IP的表示方式、子网掩码的作用
image.png
image.png
如图,IP地址分为两部分:网络号、主机号,两部分的总长度是32比特,但具体的结构实际上不固定,具体怎么表示由子网掩码确定。子网掩码二进制表示中,为1的部分对应网络号,为0的部分对应主机号。例如:255.255.255.0 这样表示的是前24比特为网络号,后8比特为主机号,图中也可以简写成”IP/24”的格式来简化子网掩码的表达。

  1. DNS查询的发出

DNS查询操作由计算机上的解析器(resolver)通过调用Socket库发起,Socket库是调用网络功能的程序组件集合,通过gethostbyname向DNS服务器查询域名的IP

DNS接力

  1. 客户端查询信息格式
  • 域名: 服务器、邮件服务器(邮件地址中@后面的部分)的名称
  • Class:在最早设计DNS方案时,DNS在互联网以外的其他网络中的应用也被考虑到了,而Class就是用来识别网络的信息。不过,如今除了互联网并没有其他的网络了,因此Class的值永远是代表互联网的IN
  • 记录类型:表示域名对应何种类型的记录
    • A:IP地址
    • MX:邮件服务器
    • PTR:根据IP反查域名
    • CNAME:域名相关别名
    • NS:查询DNS服务器的IP
    • SOA:查询域名属性
  1. 域名的层级以及查找逻辑

自己购买的域名做域名解析的时候一般会添加子域名,这就代表了域名的一个层级,实际上域名有很多的层级,域名从右到左则表示了整个域名的层级。举例:www.demo.starsea.club,这里看似`club`是最上层,实际上上面还有一层——根域,根域保存了`club`、`com`等层级的DNS服务器信息,因此从根域开始可以往下一直查找到对应域名的DNS服务器。分配给根域DNS服务器的IP地址在全世界仅有13个(不代表服务器只有13个),其地址被写到了DNS服务器程序的配置文件中,即任何DNS服务器都可以找到根域服务器。
来描述下整个查找的过程:客户端首先会访问最近的一台DNS服务器(也就是客户端的TCP/IP设置中填写的DNS服务器地址),最近的DNS服务器可以找到根域服务器,根域服务器根据域名的层级分级将查询任务给到了不同的DNS服务器,知道查找到为止。这个是一般的流程,但实际上有两种情况要考虑:1、为了加快查询,DNS服务器是有做缓存的(缓存当然也会有有效期的控制),当在缓存期限内查询过,则直接返回对应的缓存查询结果;2、一个DNS服务器通常会存多域名,因此上述的层层分发下去查找也是不确定的,如果这个域名下要查找的子域名已经在当前DNS服务器上了,那就直接返回查询结果了。

委托协议栈发送消息

查询到IP之后,客户端需要委托协议栈来发送HTTP消息给Web服务器,此处也需要通过Socket库。分为以下四个步骤。

  1. 创建套接字阶段:调用socket创建套接字,套接字创建完成后,协议栈会返回一个描述符,应用程序会将收到的描述符存放在内存中,此后得收发数据等操作都是通过这个描述符区分的。
  2. 连接阶段:调用Socket库中的名为connect的程序组件将管道连接到服务器得套接字上,携带的参数有:描述符、服务器IP地址、端口号。
  3. 通信阶段:收发数据。发送数据使用Socket的write组件完成,接收数据使用read组件。
  4. 断开阶段:调用Socket库的close程序组件断开管道并删除套接字。断开操作一般由Web服务器发起,Web服务器发送完响应消息后主动执行断开操作,之后客户端的套接字也会进入断开阶段。

协议栈和网卡

TCP协议的收发操作

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

创建套接字

套接字只是一个概念,其实体可以理解为记录了用于控制通信操作的控制信息,例如通信对象的IP地址、端口号、通信操作的进行状态等的内存空间。
协议栈是根据套接字中记录的控制信息来工作的。
创建套接字的过程为:应用程序调用socket申请创建套接字,协议栈首先会分配用于存放一个套接字所需的内存空间,并写入初始状态的控制信息。然后返回该套接字的描述符,之后应用程序在向协议栈进行收发数据委托时就需要提供这个描述符。

连接服务器
  1. 连接相关的概念

连接操作的目的:把服务器的IP地址和端口号等信息告知协议栈;客户端向服务器传达开始通信的请求;分配缓冲区(存放要收发的数据的内存空间)
TCP头部信息如下:
image.png
通信操作中使用的控制信息分为两类:

  1. 头部中记录的信息:客户端和服务器相互联络时交换的控制信息,在整个通讯过程中均需要。
    2)套接字(协议栈中的内存空间)中记录的信息:应用程序传递来的信息以及从通信对象接收到的信息都会保存在这里,还有收发数据操作的执行状态等信息也会保存在这里,协议栈会根据这些信息来执行每一步的操作。
  1. 连接操作的实际过程

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

  • 在TCP模块处创建表示连接控制信息的头部,通过TCP头部中的发送方和接收方端口号可以找到要连接的套接字。将头部中的控制位的SYN比特设置为1,用以表示连接;此外还需要设置适当的序号和窗口大小。
  • 接下来TCP模块会将信息传递给IP模块并委托它进行发送
  • 然后服务器上的IP模块会将接收到的数据传递给TCP模块,服务器的TCP模块根据TCP头部中的信息找到端口号对应的套接字,套接字中会写入相应的信息,并将状态改为正在连接。
  • 上述操作完成后,服务器的TCP模块会返回响应,这个过程和客户端一样,需要在TCP头部中设置发送方和接收方端口号以及SYN比特,此外,在返回响应时还需要将ACK控制位设为1,表示已经接收到相应的网络包。
  • 接下来,服务器TCP模块会将TCP头部传递给IP模块,并委托IP模块向客户端返回响应。
  • 客户端收到网络包之后,同样经过IP、TCP得到转化后的数字信息,SYN为1则表示连接成功,这时会向套接字中写入服务器的IP地址、端口号等信息,同时还会将状态改为连接完毕。此外,还要答复服务器,将ACK比特设置为1并发回服务器,告诉服务器刚才的响应包已经收到。

    以上连接过程则是“三次握手”的过程:1. 客户端发起连接SYN比特设置位1;2. 服务端接收到消息后,回复SYN比特为1、ACK控制位设为1、同时生成随机序号方便客户端设置网络包序号;3. 客户端收到消息后,回复ACK比特设置为1,表示响应完成。
    三次握手的最主要目的是保证连接是双工的,可靠更多的是通过重传机制来保证的。

收发数据
  1. 将HTTP请求消息交给协议栈

收发数据的起点:应用程序调用write将要发送的数据交给协议栈,协议栈仅关心一定长度的二进制字节序列。
协议栈发送数据的逻辑:1. 数据长度达到网络包的MTU(最大传输单元,包含头部。不包含头部的叫MSS),在以太网中一般是1500字节;2. 时间达到。协议栈平衡数据大小和时间来提高发送效率和性能。此外,应用程序也可以指定包立即发出。

  1. 对较大的数据进行拆分

当发送内容超过MSS(总长度超过MTU)的情况下,则需要对缓存区中的数据进行拆分,每块加上TCP头部,加上套接字中的接收方和发送方数据给到IP模块进行发送操作。
拆分之后接收方如何组装数据?此处,TCP头部的序号则起到了作用,初始序号在连接阶段双方已互相提供,此后根据每个包开始的字节数以及包的长度可以计算序号。同样,接收方需要通过ACK号告知发送方哪些拆分的包接收到了。

  1. ACK号确保数据收发可靠

ACK号的结算和作用:接收方根据序号和包长度计算出ACK号,然后返回ACK给发送方,发送方则可以知道哪些包已经发送成功了。如果超时未收到则发送失败,TCP会进行重传,如果重传到达上限则强制结束通信。如果成功了,那缓存区保存的已发送的包则可以删除了。
ACK号等待时间:上述说明中超时未收到ACK号的返回则认为失败进行重传,这个等待的时间并不是固定的。TCP会在发送数据的过程中持续测量ACK号的返回时间,如果ACK号返回变慢,则相应延长等待时间;相对地,如果ACK号马上就能返回,则相应缩短等待时间。

  1. 滑动窗口管理ACK号

上述ACK号的等待并非串行,为了收发效率,等待ACK号的同时,其他收发操作也在进行。但是如果无限制的并发,接收缓冲区将会被撑爆,因此,接收方TCP头部中的窗口字段将自己能接收的数据量告知发送方,然后发送方根据这个值对数据发送操作进行控制,这就是滑动窗口方式的基本思路。
更新窗口信息和ACK号的返回并不是独立的,都是TCP头部的字段,因此有个类似防抖的操作,可以同时回传窗口信息和ACK号,也可能单独回传,用来减少网络包提高效率。

  1. 接收HTTP响应消息
  • 浏览器在委托协议栈发送请求消息之后,会调用read程序来获取响应消息,控制流程转移到协议栈
  • 挂起:协议栈尝试从缓存区读取数据,但是此时数据还没返回,因此先挂起,等数据返回后继续操作(如何继续这块在下一章有讲解)。
  • 数据接收:协议栈会检查收到的数据块和TCP头部的内容,判断是否有数据丢失,如果没有问题则返回ACK号。协议栈将数据块暂存到接收缓冲区中,并将数据块按顺序连接起来还原出原始的数据,最后将接收到的数据复制到应用程序指定的内存地址中。
    断开连接
    断开操作
    断开操作可以由服务器和客户端任意一方发起。在Web中,Web服务器再返回响应消息,这时收发数据的过程就全部结束了,服务器一方会发起断开过程。整个断开过程就是通常的“四次挥手”的说法。以下以服务端先断开位列说明:
  1. 服务端发送FIN:服务器一方的应用程序会调用Socket库的close程序。然后,服务器的协议栈会生成包含断开信息的TCP头部,将控制位中的FIN比特设为1。接下来,协议栈会委托IP模块向客户端发送数据。
  2. 客户端返回ACK号:客户端收到服务器发来的FIN为1的TCP头部时,客户端的协议栈会将自己的套接字标记为进入断开操作状态。为了告知服务器已收到FIN为1的包,客户端会向服务器返回一个ACK号。此时,协议栈会等待应用程序调用read来读取数据。
  3. 客户端发送FIN:客户端应用程序会调用close来结束数据收发操作,这时客户端的协议栈也会和服务器一样,生成一个FIN比特为1的TCP包,然后委托IP模块发送给服务器。
  4. 服务端返回ACK号。
    删除套接字
    通讯结束之后,套接字会等待一段时间(一般为几分钟)之后删除,以防止误操作。误操作举例:假设当前是客户端先发起了断开操作,那么最后服务端发送FIN之后,正在等待ACK号返回。此时,客户端收到FIN之后立马删除了套接字,且套接字的端口也会释放,但是ACK回传的时候丢失了。那服务端会重传FIN消息,此时之前套接字的端口被其他套接字使用了,那这个FIN就会发到新创建的套接字上,于是断开操作又开始了,造成误操作。
数据收发小结

image.png

IP与以太网的包收发操作

包的组成

包由头部(目的地址等控制信息)、数据组成。其中头部包含:MAC头部、IP头部、TCP头部。
MAC头部:用于以太网协议。IP协议会查找下一个路由器的以太网地址(MAC地址),并将这个地址写入MAC头部中。这样一来,以太网协议就知道要将这个包发到哪一个路由器上了。
IP头部:用于IP协议。发送方将包的目的地,也就是要访问的服务器的IP地址写入IP头部中。这样一来,我们就知道这个包应该发往哪里,IP协议就可以根据这一地址查找包的传输方向,从而找到下一个路由器的位置。
image.png

包的收发
概述

TCP在数据块前面增加TCP头部之后委托IP模块发送包,IP模块添加IP头部、MAC头部之后再转交给网卡进行发送。

IP头部

IP模块的接收方IP地址是由TCP从应用程序获取的,而发送方的IP地址(网卡的IP)需要从路由表查询得到,我们可以通过route print命令来显示电脑的路由表。协议号:TCP为06,UDP为17。IP头部其他参数,可参考下面截图:
image.png

MAC头部

MAC头部的作用:以太网在判断网络包目的地时和TCP/IP的方式不同,因此必须采用相匹配的方式才能在以太网中将包发往目的地,而MAC头部就是干这个用的。
上一步在路由表中获取到了IP,但是MAC地址是不知道的,这个时候需要拿IP换MAC,可以使用ARP查询MAC地址,其原理是使用广播把包发给统一子网的所有设备,对应设备会响应MAC。同时ARP也使用了缓存来提高查询效率(电脑上可以输入arp命令查询arp缓存)。
以下为MAC头部的参数截图:
image.png

转化成光、电信号发出

IP模块生成的数字信息无法直接传输,需用通过网卡转化成光、电信号进行传输。

  1. 网卡驱动从IP模块获取包之后,会将其复制到网卡内的缓冲区中,然后向MAC模块发送发送包的命令。
  2. MAC模块会将包从缓冲区中取出,并在开头加上报头和起始帧分界符,在末尾加上用于检测错误的帧校验序列。

image.png
报头用来测定时机,SFD用来确定帧的起始位置,末尾的FCS(帧校验序列)用来检查包传输过程中因噪声导致的波形紊乱、数据错误,它是一串32比特的序列,是通过一个公式对包中从头到尾的所有内容进行计算而得出来的。

  1. 网卡的MAC模块生成通用信号,然后由PHY(MAU)模块转换成可在网线中传输的格式,并通过网线发送出去。同时,PHY(MAU)模块需要监控接收线路中有没有信号进来,避免信号碰撞。
    接收返回包
    PHY (MAU)模块会将信号转换成通用格式并发送给MAC模块,MAC模块再从头开始将信号转换为数字信息,并存放到缓冲区中。当到达信号的末尾时,还需要检查FCS。
    FCS校验没有问题:MAC头部中接收方MAC地址与网卡在初始化时分配给自己的MAC地址是否一致,如果不一致则直接丢弃,一致则将包放到缓存区。接着网卡需要通知计算机来取这个包,此时需要使用中断机制。
    中断机制:网卡在安装的时候在硬件中设置了中断号,在中断处理程序中则将硬件的中断号和相应的驱动程序绑定。执行中断操作的时候,网卡向扩展总线中的中断信号线发送信号,该信号线通过计算机中的中断控制器连接到CPU。当产生中断信号时,CPU会暂时挂起正在处理的任务,切换到操作系统中的中断处理程序,此时通过中断号直接拉起驱动程序从网卡的缓冲区中取出收到的包,并通过MAC头部中的以太类型字段判断协议的类型,网卡驱动就会把这样的包交给对应的协议栈。
    IP模块收到数据包之后,先判断是否有异常(例如IP是否是自己的地址),异常的话则弃包,并通过ICMP消息将错误告知发送方。无异常的话,在所有分片全部收到之后,就可以将它们还原成原始的包,这个操作叫作分片重组。然后将完整的包转给TCP模块,TCP模块TCP头部中的接收方和发送方端口号来查找对应的套接字进行后续的操作。

    UAP协议的收发操作

    在这些无需重发数据,或者是重发了也没什么意义的情况下,使用UDP发送数据的效率会更高。DNS查询,音视频等可以使用UDP。
    UDP没有TCP的接收确认、窗口等机制,因此在收发数据之前也不需要交换控制信息,也就是说不需要建立和断开连接的步骤,只要在从应用程序获取的数据前面加上UDP头部,然后交给IP进行发送就可以了。
    接收也很简单,只要根据IP头部中的接收方和发送方IP地址,以及UDP头部中的接收方和发送方端口号,找到相应的套接字并将数据交给相应的应用程序就可以了。
    以下为UDP头部:image.png

集线器、交换机和路由器

目前家庭路由器包含了集线器和交换机的功能,此处我们分开作为了解。

集线器

双绞线抑制噪声

产生噪声的原因是周围的电磁波影响。主要来自两个方面:

  1. 由电机、荧光灯、CRT显示器等设备泄漏出来的电磁波,这种电磁波来自网线之外的其他设备。信号线是用金属做成的,当电磁波接触到信号线时,会沿电磁波传播的右旋方向产生电流,这种电流会导致波形发生失真。双绞线为螺旋形,其中两根信号线中产生的噪声电流方向就会相反,从而使得噪声电流相互抵消,噪声就得到了抑制。

  2. 串扰:电流流过时就会向周围发出电磁波,这些电磁波对于其他信号线来说就成了噪声。调整每一对信号线的扭绞间隔(节距),由于正负信号线产生的噪声影响是相反的,所以两者就会相互抵消。

    工作方式

    集线器原封不动地将信号广播出去,所有接入设备均收到信号,通过MAC判断是否弃包。集线器于网卡需要交叉接线,MDI就是对RJ-45接口和信号收发模块进行直连接线,而MDI-X则是交叉接线。

    交换机

    工作原理

    交换机根据MAC地址表进行转发。MAC地址表主要包含两个信息,一个是设备的MAC地址,另一个是该设备连接在交换机的哪个端口上。
    相较于集线器的直接转发广播信号,交换机会先解包。PHY(MAU)模块以MDI-X模式进行连接,信号从网线进入PHY(MAU)后转化为通用格式,传递给MAC模块(此处的MAC模块不具有MAC地址),MAC模块将信号转换为数字信息,然后通过包末尾的FCS校验错误,如果没有问题则存放到缓冲区中。之后根据MAC地址表查找需要转发的端口。

    MAC地址表维护
  3. 添加:收到包时,将发送方MAC地址以及其输入端口的号码写入MAC地址表中。意思是,某一个端口连接的设备发包经过交换机,交换机则将对应的MAC地址和端口记录下来了。

  4. 删除:为了防止设备移动时产生问题,导致信号被转发到已删除设备的端口上,隔一段事件就会删除记录(几分钟)。

    特殊操作

    以上MAC地址表的维护产生一个疑问?如果MAC地址表中没有对应的MAC和端口信息,那信号是否就无法转发了?答案肯定不是,如果没有维护的话,交换机会像集线器一样将信号广播到所有端口。

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

    集线器犹豫是广播信号,因此不具备全双工的能力,会产生信号碰撞。使用双绞线时,发送和接收的信号线是各自独立的[插图],因此在双绞线中信号不会发生碰撞。网线连接的另一端,即交换机端口和网卡的PHY (MAU)模块以及MAC模块,其内部发送和接收电路也是各自独立的,信号也不会发生碰撞。因此交换机的全双工模式可以同时发送和接收信号。

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

    在双绞线以太网规范最初制定的时候,只规定了按一定间隔发送脉冲信号,这种信号只能用来确认网络是否正常。后来,人们又设计出了具有特定排列的脉冲信号,通过这种信号可以将自身的状态告知对方。自动协商功能就利用了这样的脉冲信号,即通过这种信号将自己能够支持的工作模式[插图]和传输速率相互告知对方,并从中选择一个最优的组合。

    交换机可同时执行多个转发操作

    交换机只将包转发到具有特定MAC地址的设备连接的端口,其他端口都是空闲的,因此其他端口也可以进行包的转发。

    路由器

    基本知识
  • 路由器是基于IP设计的,而交换机是基于以太网设计的

  • 路由器包括转发模块和端口模块两部分。转发模块负责判断包的转发目的地,端口模块负责包的收发操作。

    工作原理

    路由器在转发包时,首先会通过端口将发过来的包接收进来,这一步的工作过程取决于端口对应的通信技术。对于以太网端口来说,就是按照以太网规范进行工作,而无线局域网端口则按照无线局域网的规范工作,总之就是委托端口的硬件将包接收进来。接下来,转发模块会根据接收到的包的IP头部中记录的接收方IP地址,在路由表中进行查询,以此判断转发目标。然后,转发模块将包转移到转发目标对应的端口,端口再按照硬件的规则将包发送出去,也就是转发模块委托端口模块将包发送出去的意思。
    和交换机不同的是,路由器的各个端口都具有MAC地址和IP地址,是以实际的发送方或者接收方的身份来收发网络包的。

    路由表中的信息
  • 目标地址、子网掩码:用来展示网络号和主机号信息,路由器匹配转发目标时只进行网络号匹配,因此网络号越长匹配越精准。

  • 网关、接口:表示网络包的转发目标。根据目标地址和子网掩码匹配到某条记录后,路由器就会将网络包交给接口列中指定的网络接口(即端口)[插图],并转发到网关列中指定的IP地址。

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

    路由器的包接收操作

    信号到达网线接口部分,其中的PHY(MAU)模块和MAC模块将信号转换为数字信息,然后通过包末尾的FCS进行错误校验,如果没问题则检查MAC头部中的接收方MAC地址,看看是不是发给自己的包,如果是就放到接收缓冲区中,否则就丢弃这个包。

    查询路由表确定输出端口

    接收包之后丢弃MAC头部,再IP头部中的内容进行包的转发操作。查询路由表判断转发目标的规则:

  1. 根据网络号匹配,网络号匹配到且网络号越长的优先选择

  2. 如果存在两条网络号长度相同的记录,则选择跃点计数小的

  3. 如果没匹配到,则选择默认路由(0.0.0.0),转发到对应的网关(默认网关),此时会转发到互联网接入路由器。

  4. 如果没有默认路由且没匹配到,则直接丢弃这个包,并通过ICMP消息告知发送方。此时不能像交换机一样广播,因为路由器的工作环境是互联网,会造成网络拥塞。

    包的有效期

    从路由表中查找到转发目标之后,网络包就会被转交给输出端口发送出去。再次之前要刷新IP头部信息,其中包的有效期需要刷新,避免包转发进入死循环。
    TTL(Time to Live,生存时间)字段表示包的有效期,包每经过一个路由器的转发,这个值就会减1,当这个值变成0时,就表示超过了有效期,这个包就会被丢弃。发送方在发送包时会将TTL设为64或128。

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

    包超大的情况:

  5. 不同的线路和局域网类型各自能传输的最大包长度也不同,因此输出端口的最大包长度可能会小于输入端口

  6. 添加了一些头部数据而导致包的实际长度发生变化,ADSL、FTTH等宽带接入技术中使用的PPPoE协议就属于这种情况

判断分片的流程:

  1. 获取端口的MTU,看包是否超大
  2. 如果超过了MTU,则看IP头部中的标志字段是否支持分片,不支持则直接弃包并通过ICMP消息通知发送方。
  3. 支持分片,则进行分片。每一份上加入IP头部,大部分和之前IP头部一致,但要加入分片信息。
    路由器的发送操作和计算机相同
    其基本过程和协议栈中的IP模块发送包的过程是相同的,即在包前面加上MAC头部。其中MAC头部的MAC地址需要根据IP转化而来。转发目标的IP获取到之后,路由器通过ARP查询获取到MAC地址即为接收方的MAC地址。发送方的MAC地址是端口的MAC地址。补充其他信息之后,网络包转电信号通过端口发出。
    路由器判断下一个转发目标的方法如下:
  • 如果路由表的网关列内容为IP地址,则该地址就是下一个转发目标。
  • 如果路由表的网关列内容为空,则IP头部中的接收方IP地址就是下一个转发目标。

    路由器的附加功能

    地址转化
  1. 目的

入网设备太多,公网IP不够分了,为了解决这个问题,将内网的设备分配私有地址,路由器做地址转化完成通信。私有地址如下:

1
2
3
10.0.0.0~10.255.255.255
172.16.0.0~172.16.255.255
192.168.0.0~192.168.255.255
  1. 原理

地址转换的基本原理是在转发网络包时对IP头部中的IP地址和端口号进行改写。主要依赖于地址和端口对应表(包含:共有地址、端口号、私有地址、端口号)。TCP连接操作的第一个包被转发到互联网时,将发送方IP地址从私有地址改写成公有地址,端口号从空闲的端口中随机选择一个,之后包被发到互联网。
在后面的包收发过程中,地址转换设备需要根据对应表查找私有地址和公有地址的对应关系,再改写地址和端口号之后进行转发。当数据收发结束,进入断开阶段,访问互联网的操作全部完成后,对应表中的记录就会被删除。

  1. 从互联网访问共公司内网

默认无法从互联网访问内网,是因为对应表里没有相应的记录,那么我们只要事先手动添加这样的记录就可以了。将私有地址和端口以及公有地址和对应固定端口写道对应表里面,则互联网可以访问对应共有地址和对应端口来访问内网。

包过滤

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

接入网和网络运营商

互联网的基本结构和家庭、公司网络是相同的,但是距离和维护方式不同是两个重要的不同点。

ADSL接入网

ADSL接入线路如下图:
image.png
具体步骤如下图:
image.png

ADSL Modem将包拆分成信元

首先,互联网接入路由器会在网络包前面加上MAC头部、PPPoE头部、PPP头部总共3种头部,然后发送给ADSL Modem。
然后,ADSL Modem会把包拆分成很多小格子,每一个小格子称为一个信元。信元是一个非常小的数据块,开头是有5个字节的头部,后面是48个字节的数据,用于一种叫作ATM的通信技术。转化成信元之后,再转换成电信号发送给分离器。

ADSL将信元“调制”成信号

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

  • 振幅调制:信号振幅的大小来对应0和1
  • 相位调制:根据信号的相位来对应0和1

使用正交振幅调制的方式可以用一个波表示更多的比特,从而提高传输速率。正交振幅调制中,通过增加振幅和相位的级别,就可以增加能表示的比特数。

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

不同频率的波可以合成,也可以用滤波器从合成的波中分离出某个特定频率的波。因此,我们可以使用多个频率合成的波来传输信号,这样一来,能够表示的比特数就可以成倍提高了。ADSL就是利用了这一性质,通过多个波增加能表示的比特数来提高速率。
当Modem通电后,会发送测试信号,并根据信号的接收情况判断使用的频段数量和每个频段的比特数,这个过程称为训练(握手)。

分离器的作用
  1. 信号从用户端发出

电话和ADSL信号只是同时流到一条线路上而已,分离器实际上并没有做什么事。

  1. 信后从电话线传入

过滤掉了ADSL使用的高频信号,使电话信号传入电话机。ADSL Modem内部已经具备将ADSL频率外的信号过滤掉的功能,因此不需要在分离器进行过滤。

从用户到电话局
  1. 从分离器通过室内电话线,到达大楼的IDF(Intermediate Distribution Frame,中间配线盘)和MDF(Main Distribution Frame,主配线盘,总配线架)

  2. 到达保安器,防止雷电等情况下电话线中产生过大电流的一种保护装置,内部有保险丝。

  3. 信号会进入电线杆上架设的电话电缆

  4. 入地后进入电话局:集中埋设电缆的地方就形成了一条地道,这部分称为电缆隧道

    通过DSLAM到达BAS

    DSLAM通过读取信号波形,根据振幅和相位判断对应的比特值,将信号还原成数字信息。
    DSLAM一般不用以太网接口,而是用ATM接口,和后方路由器收发数据时使用的是原始网络包拆分后的ATM信元形式。
    BAS的操作:通过ATM接口将ATM信元转化成原始包;丢弃MAC头部和PPPoE头部,取出PPP头部以及后面的数据;BAS会在包的前面加上隧道专用头部,并发送到隧道的出口;网络包会到达隧道出口的隧道专用路由器;在这里隧道头部会被去掉,IP包会被取出,并被转发到互联网内部。

    光纤接入网(FTTH)

    基本知识

    它是由一种双层结构的纤维状透明材质(玻璃和塑料)构成的,通过在里面的纤芯中传导光信号来传输数字信息。
    电信号转光信号:电信号输入LED、激光二极管等光源后,这些光源就会根据信号电压的变化发光,高电压发光亮,低电压发光暗。
    光信号转电信号:接收端有可以感应光线的光敏元件,光敏元件可以根据光的亮度产生不同的电压。

    单模与多模光纤

    单模:较细(8~10 μm),入射角很小的光线才能进入,只能传导一条光线。对于光源和光敏元件的性能要求就较高,但信号的失真会比较小。
    双模:较粗(50 μm或62.5 μm),入射角比较大的光也可以进入,可以传导多条光线。可以降低光源和光敏元件的价格,但远距离失真较大。

    通过光纤分路来降低成本
  5. 直连方式

用一根光纤直接从用户端连接到最近的电话局,用户端的光纤收发器将以太网的电信号转换成光信号。此方式不需要再拆分信元,直接将以太网包转换成光信号,然后光信号通过连接到光纤收发器的光纤直接到达BAS前面的多路光纤收发器。
为了区分上行和下行信号的光,采用不同波长的光,混合后可以通过棱镜原理进行分离。像这样在一条光纤中使用不同的波长传输多个光信号的方式叫作波分复用。

  1. 分路方式

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

接入网中使用的PPP和隧道

用户认证和配置下发

image.png

  1. 用户向运营商的接入点拨打电话

  2. 输入用户名和密码进行登录操作

  3. 用户名和密码通过RADIUS(Remote Authentication Dial-in User Service,远程认证拨号用户服务)协议从RAS(Remote Access Server,远程访问服务器)发送到认证服务器

  4. 认证服务器校验无误后返回IP地址等配置信息,下发给用户

  5. 用户的计算机根据这些信息配置IP地址等参数,完成TCP/IP收发网络包的准备工作,接下来就可以发送TCP/IP包了

    在以太网上传输PPP消息-PPPoE

    PPP协议中没有定义以太网中的报头和FCS等元素,也没有定义信号的格式,因此无法直接将PPP消息转换成信号来发送。这里需要将PPP消息包装一层,因此使用PPPoE将PPP消息装入以太网包进行传输。
    image.png

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

    BAS除了作为用户认证的窗口之外,还可以使用隧道方式来传输网络包。隧道有两种实现方式:

  6. 使用TCP连接:在网络上的两台隧道路由器之间建立TCP连接,然后将连接两端的套接字当作是路由器的端口,并从这个端口来收发数据。

  7. 基于封装(encapsulation)实现:将包含头部在内的整个包装入另一个包中传输到隧道的另一端。

    接入网的整体工作过程
  8. 用户端的互联网接入路由器配置运营商分配的用户名和密码

  9. 接入路由器会根据PPPoE的发现机制来寻找BAS,类似于ARP广播

  10. 用户名和密码发送给BAS,两种方式:1. 将密码进行加密的CHAP(Challenge Handshake Authentication Protocol, 挑战握手认证协议),推荐方式;2. 不加密的PAP(Password Authentication Protocol, 密码验证协议)。

  11. BAS向用户下发TCP/IP配置信息(分配给上网设备的IP地址、DNS服务器的IP地址以及默认网关的IP地址)。

  12. 客户端发送包。包含MAC头部(接收方MAC地址填写通过PPPoE发现机制查询到的BAS的MAC地址,发送方MAC地址填写互联网接入路由器的BAS端的端口的MAC地址)、PPPoE头部、PPP头部。

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

    除PPPoE之外的其他方式

    PPPoAPoint-to-Point Protocol over ATM,该方式不添加MAC头部和PPPoE头部,而是直接将包装入信元中。无法通过以太网传输,但是MTU不会变小,传输效率会高点。
    DHCPDynamic Host Configuration Protocol, 动态主机配置协议。常用于通过公司网络向客户端计算机下发TCP/IP配置信息,不需要用户名和密码,不需要添加额外的PPP头部,将以太网包直接转换成ADSL信号发送给DSLAM。

    网络运营商的内部

    从接入网出来后,网络包会到达网络运营商路由器,之后会到达互联网内部。有以下两种设备:
    POPPoint of Presense, 接入点。包括各种类型的路由器对应连接不同得接入网:专线接入、拨号接入、PPPoE、PPPoA等。
    NOCNework Operation Center,网络运行中心。从POP传来的网络包都会集中到这里,并从这里被转发到离目的地更近的POP,或者是转发到其他的运营商。
    NOC和POP并没有非常严格的界定,可以简单地认为,NOC就是规模扩大后的POP。

    跨越运营商的网络包

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

    路由器自动完成路由信息交换的机制称为BGP(Border Gateway Protocol,边界网关协议)。分为两类:
    一类是将互联网中的路由全部告知对方,叫做转接。这种方式不仅会告知自己的路由信息,还会告知运营商后面的其他运营商的路由信息。
    另一种类型是两个运营商之间仅将与各自网络相关的路由信息告知对方。这样,只有双方之间的网络可以互相收发网络包,这种方式称为非转接,也叫对等。

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

    公司中使用的方式是寻找与目的地之间的最短路由,并按照最短路由来转发包。运营商除了最短路由外,还要根据客户购买的线路等信息做出限制,选择最优路由。

    IX

    Internet eXchange,互联网交换中心,通过各运营商连接到中心设备的方式来减少线路数量。
    IX的核心是具有大量高速以太网端口的二层交换机。二层交换机的基本原理和一般交换机相同,可以认为IX的核心就是大型的、高速的交换机。各个运营商的路由器通过POP或者通信线路连接到IX核心交换机上。

服务器端的局域网

Web服务器的部署地点

  1. 部署在公司内网,在Web服务器之前增加防火墙

  2. 把服务器放在网络运营商等管理的数据中心里,或者直接租用运营商提供的服务器。数据中心是与运营商核心部分NOC直接连接的,或者是与运营商之间的枢纽IX直接连接的。因此,放到数据中心部署高速可靠。

    防火墙

    防火墙可以分为包过滤、应用层网关、电路层网关等方式,,但出于性能、价格、易用性等因素,现在最为普及的是包过滤方式。包过滤的原理是:根据接收方IP地址、发送方IP地址、接收方端口号、发送方端口号、控制位等信息来判断是否允许某个包通过,因此会读取IP头部、TCP(UDP)头部等头部相关字段的信息。
    包过滤的几种场景解析:

  3. 互联网发往Web服务器的包:可以读取接收方的IP,为Web服务器IP的包允许通过;另外也可以增加发送方的IP限制。

  4. 通过端口号限定应用程序:可以读取接收方的端口限制包通过,这样可以防止其他应用程序被非法访问。例如可以限制只允许访问Web服务器的80端口。

  5. 通过控制位判断连接方向:假如有个场景需要限制Web服务器任意访问互联网,但是犹豫TCP是双向收发网络包的,因此不能直接过滤掉对应端口的包。可以通过TCP头部信息判断,禁用掉TCP控制位中SYN为1、ACK为0的包,这样Web服务器无法连接互联网了,但是TCP响应的报不会有SYN为1的情况,因此可以正常通过。

    负载均衡

    首先要用负载均衡器的IP地址代替Web服务器的实际地址注册到DNS服务器上,负载均衡器来判断要转发到哪台Web服务器。如何判断:1. 可以向Web服务器发送测试包,根据响应所需的时间来判断负载状况;2. 根据事先设置的服务器性能指数,按比例来分配请求。
    使用负载均衡器分配访问时很重要的时需要判断是否多页访问,来自一个客户端的应该在一个周期内都是分到同一台服务器了,但HTTP访问都是独立的,因此需要标识,一般可以通过增加请求头来作为区分,例如增加Cookie。

    使用缓存服务器分担负载

    除了使用多台Web服务器外,也可以将整个系统按功能分成不同的服务器,如Web服务器、数据库服务器、缓存服务器。

    缓存服务器的工作过程

    缓存服务器会添加一个If-Modified-Since头部字段并将请求转发给Web服务器,询问Web服务器用户请求的数据是否已经发生变化。Web服务器会根据If-Modified-Since的值与服务器上的页面数据的最后更新时间进行比较,如果在指定时间内数据没有变化,则返回304即可,缓存服务器将缓存返回给客户端。如果有更新则返回更新的数据,然后缓存服务器加上Via字段发送给客户端,同时将数据保存在缓存中。

    正向代理

    正向代理将代理服务器(如缓存服务器)放到客户端一侧。在使用正向代理时,一般需要在浏览器的设置窗口中的“代理服务器”一栏中填写正向代理的IP地址,浏览器发送请求消息的过程也会发生相应的变化。

    反向代理

    可以通过将请求消息中的URI中的目录名与Web服务器进行关联,使得代理能够转发一般的不包含完整网址的请求消息。nginx反向代理就是这样的逻辑。

    透明代理

    原理:缓存服务器判断转发目标的方法还有一种,那就是查看请求消息的包头部。因为包的IP头部中包含接收方IP地址(也可以是读取http头部的Host字段),只要知道了这个地址,就知道用户要访问哪台服务器了。
    过程:我们必须将透明代理放在请求消息从浏览器传输到Web服务器的路径中,当消息经过时进行拦截。因此,可以放置到接入网的入口处。

    内容分发服务

    定义

    内容分发服务:CDS(Content Delivery Service),现在常叫做CDN(Content Delivery Network或Content Distribution Network)。
    CDSP:Content Delivery Service Provider,内容分发服务运营商。

    原理

    CDSP会与主要的供应商签约,并部署很多台缓存服务器,然后CDSP会与Web服务器运营者签约。只要Web服务器与缓存服务器建立关联,那么当客户端访问Web服务器时,实际上就是在访问CDSP的缓存服务器了。

    寻找最近的缓存服务器
  6. 通过DNS查询寻找

首先服务端的DNS服务器从缓存服务器部署地点的路由器收集路由信息,然后根据路由表查询到各缓存服务器到客户端DNS服务器的路由信息。根据该路由信息中经过了多少运营商来估算远近,最后返回最近的服务器的IP地址给客户端DNS服务器。

  1. 通过重定向服务器分配访问目标
    1. 将重定向服务器的IP注册到Web服务器端的DNS服务器上
    2. 重定向服务器收集了来自各个路由器的路由信息
    3. 根据路由信息找到最近的缓存服务器,并将缓存服务器地址写到Location字段返回给客户端(这就是302重定向)
    4. 客户端的请求重定向到最近的缓存服务器,这才是请求的真正目标

缺点:增加了HTTP消息的交互次数,开销增大;优点:相较于通过DNS查询,这里查找最近的缓存服务器使用的是HTTP请求头中的IP,因此精度更高。

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

数据更新后第一次访问的时候缓存服务器必然回去取原始数据,然后刷新缓存,这样增大的开销。因此一般内存分发服务的缓存服务器具有这样的功能,当Web服务器在原始数据发生更新时,立即通知缓存服务器,使得缓存服务器上的数据一直保持最新状态,这样第一次访问就有缓存效果。

请求到达Web服务器,响应返回浏览器

服务器概览

服务器包含两个模块:等待连接模块,负责与客户端通信的模块。
服务端的收发过程如下:
(1)创建套接字(创建套接字阶段)
(2-1)将套接字设置为等待连接状态(等待连接阶段)
(2-2)接受连接(接受连接阶段)
(3)收发数据(收发阶段)
(4)断开管道并删除套接字(断开阶段)

服务器端的套接字和端口号
  1. 套接字的创建和连接过程
    1. 协议栈调用socket创建套接字
    2. 协议栈调用bind将端口号写入套接字中,例如Web服务器使用80端口
    3. 协议栈调用listen向套接字写入等待连接状态这一控制信息,套接字开始等待来自客户端的连接网络包
    4. 协议栈调用accept来接受连接。这是还没有包到来,一般来说服务器端都是处于等待包到达的状态,这时应用程序会暂停运行。客户端的包到达,返回响应包并开始接受连接操作。协议栈会给等待连接的套接字复制一个副本,然后将连接对象等控制信息写入新的套接字中。
    5. accept结束之后,等待连接的过程也就结束了,这时等待连接模块会启动客户端通信模块,然后将连接好的新套接字转交给客户端通信模块。
  2. 复制新套接字的作用

服务端是一对多的场景,需要复制新套接字用来传输数据,而旧的套接字要继续等待新的连接。且要保持两端的套接字正常连接,需要复制的套接字具有相同的端口。但是一个端口无法识别多个套接字,因此服务端的协议栈需要四个信息(客户端IP地址、客户端端口号、服务器IP地址、服务器端口号)来判断连接哪个套接字。
但是套接字的描述符依然需要,因为:1. 等待连接的套接字中没有客户端IP地址和端口号;使用描述符这一种信息比较简单。出于这两个原因,应用程序和协议栈之间是使用描述符来指代套接字的。

服务器的接收操作

网卡将接收到的信号转换成数字信息

网卡的MAC模块将网络包从信号还原为数字信息,校验FCS并存入缓冲区。之后网卡通过中断将网络包到达的事件通知给CPU,CPU暂停当前工作并切换到网卡的任务。网卡驱动会根据MAC头部判断协议类型,并将包交给相应的协议栈。

IP模块的接收操作

到达协议栈之后IP模块开始工作,检查IP头部,(1)判断是不是发给自己的;(2)判断网络包是否经过分片;(3)将包转交给TCP模块或UDP模块

TCP模块如何处理连接包

如果收到的是发起连接的包,则TCP模块会(1)确认TCP头部的控制位SYN; (2)检查接收方端口号;(3)为相应的等待连接套接字复制一个新的副本;(4)记录发送方IP地址和端口号等信息。

TCP模块如何处理数据包

收到数据包时,TCP模块会(1)根据收到的包的发送方IP地址、发送方端口号、接收方IP地址、接收方端口号找到相对应的套接字;(2)将数据块拼合起来并保存在接收缓冲区中;(3)向客户端返回ACK。

TCP模块的断开操作

断开操作可以由客户端或服务器任何一方发起,具体的顺序是由应用层协议决定的。在HTTP1.0中,是服务器先发起断开操作,HTTP1.1中,是客户端先发起断开操作。
和之前在协议和网卡中介绍的断开操作一样,这里进行“四次挥手”:调用Socket库的close, TCP模块会生成一个控制位FIN为1的TCP头部,并委托IP模块发送给客户端。当客户端收到这个包之后,会返回一个ACK号。接下来客户端调用close,生成一个FIN为1的TCP头部发给服务器,服务器再返回ACK号,这时断开操作就完成了。

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

将请求的URI转换为实际的文件名

URI访问的目录和实际服务器的文件目录并不会对应,这样可以控制客户端目录的访问。因此,需要设置好目录改写的规则,当URI中的路径符合改写规则时,就可以将URI中的文件名改写成其他的文件名进行访问。

运行CGI程序

目前接触到的项目中,基本不会使用CGI程序,这里只是做个介绍。
Web服务器会检查URI指定的文件名,将.cgi、.php等扩展名的文件设置为程序,当遇到这些文件时,Web服务器就会将它们作为程序来对待。应用程序输出的数据一般来说会嵌入到HTML文档中,因此Web服务器可以直接将其作为响应消息返回给客户端。

Web服务器的访问控制

访问控制规则主要有以下3种:客户端IP地址、客户端域名、用户名和密码。

返回响应消息

首先,Web服务器调用Socket库的write,将响应消息交给协议栈。并将对应套接字的描述符给到协议栈即可知道通信状态。协议栈会将数据拆分成多个网络包,然后加上头部发送出去。这些包中包含接收方客户端的地址,它们将经过交换机和路由器的转发,通过互联网最终到达客户端。

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

浏览器根据响应头中的Content-Type来渲染指定格式的文件,有时也会结合文件扩展名(例如.html)来展示。

网络包的路程

image.png
image.png