Taogen's Blog

Stay hungry stay foolish.

介绍链路层

两个相邻的连接的节点之间的通信路径称为链路。任何设备运行一个链路层协议称为一个节点。链路层的主要功能是通过把网络层的数据报封装为链路层的帧(Frame)在链路上传播,从而将网络层数据报从一个节点传输到另一个相邻的节点。链路的信道(Channel)主要有两种类型:点到点通信链路(Point-to-point Link)和广播信道(Broadcast Channel)。常见的点到点通信链路有:以太网链路和广域网链路。

链路层提供的服务

  • 封装。将网络层的数据报封装成链路层的帧。
  • 链路接入。
  • 不可靠数据传输。
  • 错误侦测和纠正。

链路层的硬件组成

网络接口控制器(Network Interface Controller,NIC),也称网卡(Network Card),网络适配器(Network Adapter),局域网适配器,物理网络接口等等。它是一个计算机的硬件组件,它连接了计算机和计算机网络。本篇主要使用网络适配器作为名称,网络适配器的外观如下图所示。

在一台主机中应用层、传输层和网络层都是软件组件,而链路层一部分是软件组件,一部分是硬件组件。网络协议栈与主机软件和硬件组件之间的关系如下图所示。

链路层软件组件主要和网络层交互。在客户端组装链路层寻址信息,激活网络适配器;在服务端响应网络适配器的 interrupt 信号,传递数据报给网络层。硬件组件功能是错误侦测,以及物理层交互。

错误检测与纠正

奇偶校验

1. 简单的奇偶校验 (One-bit Parity)

通过使用一个 parity bit 来侦察错误。将1位 parity bit 放在数据包的后面。

偶数校验,保证 data bits + parity bit 所有 1 的个数等于偶数。如果 data 中所有的1的个数为奇数,则 parity bit 为 1,否则为0。data中所有的1的个数为偶数,则parity bit 为 0。

奇数校验则保证 data bits + parity bit 所有 1 的个数等于奇数。

2. 二维奇偶检验 (Two-Dimensional Parity,2D parity)

将报文的二进制数据分为 i 行 j 列,每行的末尾和每列的末尾都添加一个 parity bit,一共添加 i+j+1 个 parity bits。它的每行每列都遵循奇偶校验规则。它不仅可以侦测错误,还可以进行错误纠正。

奇偶检验的缺点:

  • 简单的奇偶检验和二维奇偶校验都不能侦测所有错误。
  • 简单的奇偶检验仅能侦测到一位发生错误。不能侦测一位0和一位1交换错误,两位0或1变为两位1或0错误。
  • 二维奇偶校验能更好的侦测错误,但需要更多的检验位。

检验和

检验和(Checksum)实现原理是将数据作分为多个16位二进制求和,求和的反码作为检验和携带在报文头部。接收方将数据划分为多个16位与检验和求和,结果所有的位都是 1 则正确,出现 0 表示错误。

循环冗余校验

循环冗余校验(Cyclic Redundancy Check (CRC))编码也称多项式编码。要得到 CRC code 需要定义一个生成器多项式。这个多项式的系数作为除数,数据报文作为被除数,得到的余数为 CRC code。如,多项式为 x^7 + x^6 + x^4 + x^3 + x + 1,1x^7 + 1x^6 + 0x^5 + x^4 + x^3 + 0x^2 + 1x + 1x^0,除数为 11011011。

发送方:

  • n 个 0 附加在数据报文后面,n 是位数小于 CRC generator。
  • 新的数据单元除以 CRC generator 得到的余数称为 CRC。
  • 将数据单元之前添加的 n 个 0 替换成 CRC。
  • 数据单元加上 CRC 传输给接收方。

接收方:

  • 接收的数据除以 CRC generator,检查余数。
  • 如果余数为 0 则数据正确,否则数据错误。

多点连接链路和协议

广播链路可以有多个发送端和接收端同时连接同一个广播信道。解决多个节点同时发送和接收在同一个信道的问题称为多点连接问题(Multiple Access Problem)。多个节点直接通过一个广播信道会产生数据帧的碰撞(Collide),造成数据丢失。多点连接协议就是为了解决多点连接碰撞问题的。常见的多点连接协议类型有:信道划分协议(Channel Partitioning Protocols),随机接入协议(Random Access Protocols),轮流协议(Taking-turns Protocols)

信道划分协议可分为:

  • 时分多路复用(Time-Division Multiplexing,TDM)。每个节点轮流使用一小段时间。
  • 频分多路复用(Frequency-Division Multiplexing,FDM)。每个节点使用不同的频率。频率的带宽为 R/N bps。
  • 码分多址(Code Division Multiple Access,CDMA)。每个节点使用唯一的代码去编码数据。多个的节点可以同时发送和接收编码的数据。

局域网

链路层寻址和 ARP 协议

链路层通信使用的是 MAC 地址,数据报文的转发依靠 Switch Table 查询目标 MAC 地址对应的输出链路来进行转发。主机和路由器每个网络接口既有一个 IP 地址也有一个 MAC 地址。ARP 协议可以通过广播 ARP 查询请求得到目标 IP 地址对应的 MAC 地址。链路层广播地址为 FF-FF-FF-FF-FF。

MAC 地址

MAC 地址是链路层地址,也称物理地址。每个主机或路由器的网络接口都有一个唯一的固定的 MAC 地址。一个 MAC 地址占 6 个字节,使用十六进制数字表示。如,5c-66-AB-90-75-B1。MAC 地址是由 IEEE 组成统一管理的,它保证了世界上每个设备网络接口 MAC 地址是唯一。

为什么有了 IP 地址还需要 MAC 地址呢?因为当设备位置发生改变时,它的 IP 地址也会改变。而 MAC 地址是设置在硬件上的,一般是固定不变的。这样可以唯一的标识一个设备。IP 地址就像是一个人的邮寄地址,而 MAC 地址就行是一个人的身份证号码。

ARP 协议

ARP(Address Resolution Protocol)协议可以将 IP 地址转换为 MAC 地址。它是怎么做到的呢?每一个主机和路由器都有一个 ARP 表,它记录了一个子网中的 IP 地址对应的 MAC 地址。ARP 表结构如下图所示:

ARP 只能处理在同一个子网的 IP 地址,因为它使用的是广播的方式。在一个局域网中,一个主机 A 直到另一个主机 B 的 IP 地址,主机 A 发生链路层报文时,需要知道主机 B 的 MAC 地址。其过程如下:

  • 主机 A 在它的 ARP 表中寻找主机 B 的记录,如果找到了,使用里面的 MAC 地址即可。
  • 如果没找到,则需要通过链路层广播,发送 ARP 查询请求。在这个局域网中的所有主机和路由器都会收到这个请求。
  • 每个设备检查 ARP 报文中目标 IP 地址是否与自己的匹配,主机 B 的IP 地址与目标地址匹配,主机 B 单播响应请求,发送的 ARP 响应报文包含自己的 MAC 地址。其它不匹配的主机不做响应。
  • 主机 A 接收到响应,知道了主机 B 的 MAC 地址,然后封装 链路层报文与主机 B 通信,并更新自己的 ARP 表。

ARP 时即插即用的,不需要配置。

发送报文在两个不同的子网

在同一个局域网两个主机通信是通过 MAC 地址进行数据转发的,如交换机的 switch table 记录了MAC 地址对应的链路接口。

不同的两个局域网需要通过在路由器进行 IP 转发。其过程如下:

  • 主机 A 将广播 ARP 请求,想要目标 IP 地址的 MAC 地址。
  • 路由器的网络接口发现目标 IP 地址不在这个子网,需要通过路由器 IP 转发,所以路由器响应自己的 MAC 地址给主机 A。
  • 主机 A 把路由器当作目标主机。主机 A 把报文发给路由器,路由器通过转发表传给下一跳路由器,经过多个路由器的转发,最终到达目标 IP 地址的主机 B。

以太网协议

以太网(Ethernet)是最流行的构建局域网的技术。早先的以太网使用的是广播的形式通信,后来使用交换机存储转发的形式。

以太网的帧结构如下图所示:

Preamble:唤醒接收端的网络适配器,以及时钟同步。占8字节。

Destination address:表示目标网络适配器的 MAC 地址。占6字节。

Source address:表示源网络适配器 MAC 地址。占6字节。

Type:表示上层协议的类型。占2字节。

Data:IP 报文数据。46 到 1500 字节。

CRC:错误校验。循环冗余检验码。占4字节。

链路层交换机

交换机接收链路报文和转发它们到指定的输出链路。交换机对于路由器和主机是透明的,它们不会意识到交换机的存在。交换机没有 IP 地址和 MAC 地址。

交换机的主要功能:

  • 过滤。交换机可以判断什么帧可以转发,什么帧需要丢弃。
  • 转发。将接收到的帧转发到某个输出链路。

交换机的工作原理:

  • 交换机通过查询转换表(Switch Table)来进行转发。交换表格式如下图所示。
  • 如果找到了输出链路,则进行转发;没有找到指定的输出链路,则进行广播。

交换机是自学习的,转换表是自动的更新和维护的。初始转换表设置为空。每个请求经过交换机都会更新路由交换表,记录请求中源 MAC 地址对应的输入链路。当一定时间内,转换表中的一个 MAC 地址没有接收任何报文,这个记录就会被删除。

交换机是即插即用不用配置和不同人工干预的。它是全双工的,每个接口可以同时接收和发送数据。

交换机和路由器的对比

Hub Router Switch
连接隔离 No Yes Yes
即插即用 Yes No Yes
最优路由 No Yes No

References

[1] Computer Networking: A Top-Down Approach, by Jim Kurose

[2] Network interface controller - Wikipedia

[3] Cyclic redundancy check - Wikipedia

[4] Cyclic redundancy check - SlideShare

介绍网络层

网络层提供了两个主机(终端)的信息传输服务。相比于应用层和传输层,它们提供的服务是一台主机的一个进程与另一台主机的一个进程之间的通信,它们是与进程绑定的,而网络层是与主机绑定的,一个主机在网络中通过 IP 地址进行唯一标识。

因特网的结构

因特网可以分为网络的边缘和网络的中心。网络的边缘是一个路由器连接着各种各样的终端设备,如电脑,手机等。网络的中心是由许许多多的路由连接起来的一个网状结构,它组成了网络的骨架,。因特网的结构如下图所示:

应用层和传输层只出现网络边缘的终端设备上。在网络的中心的路由器上没有应用层和传输层,最高层为网络层,它负责传输网络层数据。

应用层和传输层是两个终端设备上的进程之间的通信,它们只关心进程发给网络层的数据是什么样的,以及从网络层接收到的数据是什么样的。它们不管网络的结构是什么样的,数据是如何在网络中传输的。

网络层实现的功能

网络层主要实现在两个主机之间的网络通信,它要将一个主机上的数据,经过网络(多个路由器),传递给另一个主机。要实现这个功能,需要解决两个问题:1. 网络层数据如何在一个路由器节点上传输?2. 网络层数据如何选择一条最快的网络路径进行数据传输?

路由器上的数据传输是指数据包从路由器的一个输入链路接口传输到一个输出链路接口。这个功能是通过硬件实现的。而选择路径即路由,路由一般是通过软件实现的。

网络层的数据转发(Forwarding)

网络层的信息通信,是将网络层的数据报(Datagram)从客户端主机,经过许多个路由器的转发,最终传递到服务端主机。为了了解网络层数据是如何转发的?我们先介绍路由器的内部工作原理。然后介绍数据报转发过程中用到的 IP 协议。

路由器是如何工作的


路由器的结构

路由器结构如下图所示。它主要由以下四个部分组成。

  • 输入端口(Input Port):输入端口执行三个步骤。第一步执行物理层的功能,终止传入的物理链路。第二步执行链路层功能,与传入链路另一侧的链路层相互操作。第三步,查询转发表,判断将数据传送到哪个输出端口。
  • 交换结构(Switch Fabric):连接输入端口和输出端口。
  • 输出端口(Output Port):接受交换结构的数据,传播这些数据到输出链路。
  • 路由选择处理器(Routing Processor):维护路由表和链路状态信息,计算路由器的转发表。

路由表和转发表的区别是什么?

路由表是每个路由器用来计算和维护网络拓扑结构中的最小花费路径。它每一个行记录了目标地址(Destination),网络掩码(Mask),和下一跳 IP 地址(Next Hop)等等。

转发表用来查询 IP 报文转发到哪个输出端口。

路由器的工作原理

1. 输入端口主要是实现查询报文的输出端口的功能。通过在转发表中查询匹配目标 IP 地址的前缀,从而得到对应的输出端口。如果目标地址匹配多个前缀,则使用最长前缀匹配规则(Longest Prefix Matching Rule)。

2. 转换组织的实现方式有很多种。常用的三种实现方式如下:

Memory(内存)。拷贝数据包到输出端口的内存区域。缺点是多个数据包不能同时读写内存。

Bus(总线)。输入端口将数据包直接传输给输出端口。缺点是多个数据包不能同时使用 bus。

Crossbar(交叉开关矩阵)。由 2N 个bus 连接 N 个输入端口和 N 个输出端口。可以同时传输多个数据包。缺点是不能同时传输多个同一输出端口的数据包。

3. 输出端口,从内存区域的队列中选择一个数据包出队,将使数据包封装成帧在链路上传输。

路由器的等待队列和数据调度

路由器的等待队列可能发生在输入端口和输出端口。队列的长度却决于网络的负载与路由器的处理的速度。当网络的负载超过路由器的处理速度,最终会导致没有足够的内存可用,产生丢包后果。

输入端口队列中的数据包等待着通过交换结构传输到输出端口。输出端口队列中的数据包等待传输到链路上。

在输出端口通常使用调度算法,控制数据包的传输的顺序。常见的调度算法有:

  • First-in-First-Out (FIFO),先进先出算法,使用简单的规则,最先到达的数据包最先处理。
  • Priority Queueing,优先队列,按优先度分为不同的队列,先处理高优先度的队列,再处理低优先度的队列。
  • Round Robin and Weighted Fair Queuing (WFQ),循环与加权公平队列,按照优先度分为不同的队列,每个队列依次循环处理。

IP 协议和 IP 寻址


IPv4 协议


IPv4 的报文格式

IPv4 协议定义了 IP 报文的数据格式。IPv4的数据报文格式如下图所示。

报文字段解释

  • Version:占4位,指定了 IP 协议的版本。
  • Header length:表示头部的长度。长度=20字节+Options的长度。
  • Type of service:用于标识报文是实时应用,还是非实时应用报文。实时应用如网络电话。非实时应用如FTP。
  • Datagram length:表示整个报文的长度,头部+数据域。
  • Identifier,Flags,Fragmentation offset:用于 IP 报文分片。
  • Time-to-live:可存活的时间。当TTL=0时,数据报需要被丢弃。
  • Protocol:指出使用的传输层的协议。
  • Header checksum:用于 IP 报文错误检查。
  • Source IP address,Destination IP address:表示客户端和服务端主机的 IP 地址。
  • Options:用于 IP 头部的扩展。一般很少使用。
  • Data:数据负载。传输层数报文段或者ICMP消息。
IPv4 报文分片(Datagram Fragmentation)

链路层有不同的链路类型,不同的链路有不同的最大传输单元(Maximum Transmission Unit,MTU)。在链路上,一般一个网络层的 IP 报文封装一个链路层的帧。由于不同的链路有不同的 MTU,会导致一个 IP 报文在一个链路能传输,而在另一个链路由于 IP 报文长度大于该链路的 MTU,而不能在该链路传输。如,以太网链路最大传输单元为1500 bytes,而广域网链路最大传输单元为 576 bytes。

为了解决这个问题,需要用到 IP 报文分片。当 IP 报文长度大于该链路的 MTU 时,将 IP 报文分为多个分片(Fragment),每个分片封装成一个帧在链路上传输。

IP 报文分片头部设置为:每个分片设置相同的 identification number;前面的分片 flag bit 设为 1,最后一个分片 flag bit 设为 0;offset 指定分片在原始的 IP 报文中的相对位置,第一个分片 offset 设为 0。

IP 报文分片检查。路由器通过相同的 identification number 判断是一个 IP 报文分片,通过 flag 判断分片是否结束,通过 offset 知道分片的顺序。

IP 寻址

IP 寻址(IP Addressing)是指对某个 IP 地址进行定位。其中涉及到许多网络概念,如 IP 地址,接口,子网,子网掩码等等。下面对这些概念进行简单描述。

接口(Interface):连接主机和物理链路边界。每台主机有一个接口,路由器通常由多个接口。

IP 地址:每个接口必须有一个 IP 地址。IPv4 地址占 32 位。地址的表示为,4个十进制的数字以点分隔,如193.32.216.9。

子网(Subnet):由一个路由器接口和多个主机(或路由器)接口互相连接的网络称为一个子网。IP 网络可以划分为很多个子网。同一个子网的所有接口具有相同的 IP 地址前缀。

子网掩码:表示一个子网的相同的 IP 地址前缀。一般形式为 a.b.c.d/x,其中 x 表示前缀的长度。如一个子网的子网掩码为 233.1.1.0/24,那么这个子网中所有的接口 IP 地址有共同的24位前缀 233.1.1…,IP 地址可以为 233.1.1.1,233.1.1.2,233.1.1.3 等等。

有类别的寻址(Classful Addressing):网络划分中IP地址的前缀位数限制为8,16,24位。

无类域间路由(Classless Inter-Domain Routing, CIDR):CIDR用 13-27位长的前缀取代了有类别寻址限制的3种前缀。

IP 广播地址(Broadcast Address):IP 广播地址为 255.255.255.255,发送报文给广播地址,这个子网的所有主机都能收到这个消息。

获取一组 IP 地址

一个机构或公司想要获取一组 IP 地址,构建自己的子网。需要从网络提供商(Internet Support Provider, ISP) 那里获取。如中国电信和中国移动等。

ISP 如何获得一组 IP 地址。IP 地址是被一个权威组织 ICANN (Internet Corporation for Assigned Names and Numbers)所管理的。ISP 可以从权威组织那里获取一组 IP 地址。

获取一个主机的 IP 地址

一台主机想要连接互联网,需要获取一个 IP 地址。为主机分配 IP 地址可以手动配置,也可以使用DHCP( Dynamic Host Configuration Protocol)协议来自动分配。DHCP 协议是即插即用的零配置的协议。

DHCP 协议分配IP地址的过程:

  • 新接入网络的主机发送获取 IP 地址请求,通过广播 DHCP discover message。
  • DHCP 服务器响应请求,返回分配的 IP 地址,子网掩码,和 IP 地址租用时间。通过广播 DHCP offer message。
  • 主机发送请求确认,通过广播 DHCP request message。
  • DHCP 服务器响应请求,确认请求参数。通过广播 DHCP ACK message。

NAT

一台服务器主机需要被网络访问,优先需要拥有一个广域网 IP 地址。当服务器主机不断扩展增加,没有足够的 IP 地址时,可以通过 Network Address Translation (NAT) 可以进行 IP 地址扩展。可以将一个广域网 IP 地址,扩展为多个局域网 IP 地址。即一个广域网 IP 地址,通过映射局域网 IP 地址,可以为多台主机提供网络接入。

NAT 的工作原理是:

  • 所有的主机与 NAT 路由器连接,所有的主机对于外部世界看作是单个设备和一个 IP 地址,通过这一个 IP 地址不同的端口来区分内部的主机。
  • NAT 使用 NAT 转换表(NAT Translation Table) 将这个公开的 IP 地址加端口和所有内网 IP 地址加端口之间有一对一映射关系。也就是 NAT 转换表的一个记录,将公网 IP 和一个端口映射一个内网的进程。
  • 外部客户端请求 NAT 内的主机,是通过请求 NAT 路由器的 IP 地址和指定端口,NAT 路由器接收到请求后,通过修改报文的目标地址为局域网地址,修改目标端口为进程的端口,将这个报文转发给内网的主机的一个进程。
  • NAT 内的主机访问外部的主机,请求经过 NAT 路由器的时候,NAT 路由器修改报文的源地址为 NAT 路由器的地址,修改源端口为 NAT 路由器的一个端口。
  • 所有内网中的主机不直接与外部的通信,所有的通信都是 NAT 路由器与外部进行的。NAT 通过修改报文的内容从而达到与内网的通信。

NAT 转换表如下图所示:

IPv6 协议

由于 IPv4 的地址空间快用完了。需要一个新的 IP 协议支持更多的 IP 地址,所有 IPv6 诞生了。

IPv6 相比与IPv4有哪些重大的改变:

  • 扩展了地址空间。IP 地址由原来的32位变成128位。
  • 支持任播 anycast address。多个主机使用相同的 IP 地址,路由器优先访问离自己最近的一个。相当于 CDN 的功能。
  • 固定的40字节的报文头部。固定的报文头部使得 IP 报文可以被路由器处理得更快。
  • 流标签。定义报文数据流的类型。

IPv6 的报文格式如下图所示:

报文字段解释

  • Version:表示协议的版本。
  • Traffic class:表示服务的类型。指定报文的优先度。
  • Flow label:表示流的类型。实时应用还是非实时应用。
  • Payload length:数据域的长度。
  • Next header:指定传输层的协议类型。TCP 还是 UDP。
  • Hop limit:在路由器中转发的次数。当 hot limit 为0是该报文将被丢弃。
  • Source and destination address:源 IP 地址和目标 IP 地址。
  • Data:数据域。

IPv6 相对于 IPv4 去除的字段

  • Fragmentation:IPv6 不需要分片。当报文长度大于链路最大传输单元时,该报文直接被丢弃,而不是进行分片。
  • Header checksum:不再执行错误检查。传输层和链路层的错误检查已经足够了。
  • Options:IPv6 使用固定的头部,不需要可选字段。

网络层的路由管理(Routing)

路由表记录和维护着网络通信的最小花费路径,通过路由表使整个网络通信更加高效。路由表则是通过路由算法和路由协议得到的。这一小节主要讲述常见的路由算法和路由协议。

路由算法

网络结构像是一个由多个节点相互连接的图。一个图结构有 N 个节点和 E 条边组成。每一个相邻的节点称为邻居,任意两个连通的节点形成的一条路径。路由算法就是算出任意两个节点之间的最小花费路径(Least-cost path)。

路由算法可以通过很多方式实现,可以将它们进行分类:

  • 集中路由算法,分散路由算法
  • 静态路由算法,动态路由算法
  • 负载敏感算法,负载不敏感的算法

LS 算法是一个集中式路由算法,它采用了 Dijkstra 算法计算最小花费路径。使用的方式是:每个路由器运行 LS 算法,计算与其它每个节点的最小花费路径。

LS 算法的描述

初始化过程:计算相邻的节点的路径花费。不相邻的节点初始化为无穷大。

循环过程:循环计算当源节点到目标节点(邻居的邻居节点)的最小路径,直到所有节点都经过计算。

算法伪代码如下:

/* 
D(v): cost of least-cost path from the source node to desination v.
c(u,v): cost of from u to directly attached neighbor v.
N: all nodes
N': subset of nodes.
Time complexity: O(n^2)
*/
Initialization:
N' = {u}
for all nodes v
if v is a neighbor of u
then D(v) = c(u,v)
else D(v) = ∞

Loop
find w not in N' such that D(w) is a minimum
add w to N'
update D(v) for each neighbor v of w and not in N'
D(v) = min(D(v), D(w) + c(w,v))
util N' = N

Distance-Vector (DV) 路由算法

DV 算法是一个异步,分散的算法。

DV 算法描述

Initialization:
for all destination y in N:
Dx(y) = c(x,y) /* if y is not a neighbor then c(x,y) = ∞ */
for each neighbor w
Dw(y) = ? for all destinations y in N
for each neighbor w
send distance vector Dx = [Dx(y): y in N] to w

loop
wait (until I see a link cost change to some neighbor w or until I receive a distance vector form some neighbor w)
for each y in N:
Dx(y) = min{c(x,v) + Dv(y)}
if Dx(y) changed for any destination y
send distance vector Dx = [Dx(y): y in N] to all neighbors
forever

LS 和 DV 路由算法的比较

  • 消息复杂度。LS 算法需要直到每一条网络链路的花费。这需要 O(NE) 消息发送。当一个链路花费发生改变时需要把新的花费发给所有节点。DV 算法需要在所有直接连接的邻居之间交换消息。这个复杂度取决于很多因素。当一个链路花费发送改变时,新的花费将通过一个节点向和它连接的节点进行传播。
  • 收敛速度。LS 是一个 O(N^2) 的算法需要 O(NE) 个消息传递。DV 算法没有明确的复杂度,可能会导致无限死循环。
  • 鲁棒性。LS 算法计算是每个路由器独立的,一个路由器的计算机结果不会受其它路由器的影响。DV 算法根据所有的邻居来计算,当一个节点出现错误时,可能导致整个网络出现错误计算。

两个算法都有自己的优缺点,它们都使用在当今的因特网中。

路由协议

想要计算和维护任何一个路由器节点到世界范围内的其它所有路由器节点的最小花费路径,是一件很复杂的事情。主要的问题有两个方面。

  • 网络规模。目前世界上有数亿的路由器节点。想要计算和存储如此多的路径信息,需要很多的计算时间和存储空间。
  • 网络管理。每个国家每个地区,希望能够自己控制和管理自己的网络,以及隐藏自己内部的网络结构。

为了解决这些问题,每个地区可以通过一组路由器构建一个自治系统(Autonomous System, AS)。如今世界上存在的因特网,就是由很多个 AS 组成的网络,一个 AS 与另一个 AS 之间直接或间接地连接和沟通,就连通了整个因特网。一个 ISP(网络服务提供商) 通常会组建一个自己的网络自治系统,也有的 ISP 会组建多层级的自治系统。当今世界的因特网的结构大致如下图所示:

一个 AS (或者 ISP )内部的路由管理,通过自治系统内部路由协议(Intra-Autonomous System Routing Protocol)实现,一个 AS 内的所有路由器运行相同的路由算法。常见的协议,如 OSPF 协议。

AS 之间的路由管理,通过自治系统间的路由协议(Inter-Autonomous system routing protocol)实现,每个 AS 运行相同的自治系统间的路由协议进行交流。常见的协议,如 BGP 协议。

ISP 内部路由管理:OSPF 协议

OSPF 协议使用 link-state 路由算法计算 ISP 内部任何两个节点之间的最小花费路径。OSPF 不是当链路发生改变时运行,而是每个路由器定期(每30分钟)向其它路由器的广播路由信息。OSPF 消息是使用 IP 报文进行负载的。

ISP之间的路由管理:BGP 协议

在因特网中,所有的AS运行相同的 inter-AS 路由协议称为边界网关协议(Border Gateway Protocol, BGP)。在 BGP 协议中,每个 AS 有自己的一组 IP 地址,通常是连续的有相同前缀的 IP 地址。一个 AS 通过CIDR 前缀向其它 AS 广播自己的存在。

BGP 协议提供的服务

  • 一个 AS 通过 AS 邻居获取可到达的网络 IP 前缀信息。
  • 提供一个最好的路径从一个 AS 到达另一个 AS。

关于 BGP 协议是如何广播一个 AS 的存在,以及如何计算最佳的AS 间的路径,这里不详细展开。详细内容可以查阅最后的参考书籍。

网络的管理

ICMP 协议

通过 ICMP (Internet Control Message Protocol) 协议,主机和路由器之间可以进行交流。ICMP 报文是使用 IP 报文进行负载的,通过设置头部的 upper-layer protocol number 为 1,主机可以识别这个一个 ICMP 报文,而不是 TCP 或 UDP 报文。ICMP 报文有类型和代码表示不同的含义。如,当一个主机不可访问时,路由器会返回 ICMP 报文给客户端,报文设置为 type=3,code=1 表示目标主机不可接入。

ICMP 常见的功能

  • 报告错误。
  • 实现 ping 程序。
  • 拥塞控制。
  • 实现路由追踪程序。

网络管理和 SNMP 协议

一个网络有很多的硬件和软件组件构成,如链路,交换机,路由器,主机等。当成千上万的组件组成一个网络,想要把保持网络的持续稳定的运行,是一件很有挑战的事。通过一些网络管理工具和技术可以帮助网络管理员监控,管理,和控制网络。

关键的网络管理组件

  • 管理服务器。
  • 管理的设备。
  • 管理信息。定义了管理信息的格式。
  • 网络管理代理。运行在设备上,可以与服务器进行交流。
  • 网络管理协议。网络协议允许管理服务器查询和修改设备的状态。网络管理代理可以给管理服务器通知异常时间。常见的网络管理协议 SNMP。

SNMP 协议(The Simple Network Management Protocol) 是一个应用层协议。它在管理服务器和网络管理代理之间传达网络管理控制和信息。

References

[1] Computer Networking: A Top-Down Approach, by Jim Kurose

[2] IP 寻址的工作原理

介绍传输层

什么是传输层

应用层提供的服务是让两个终端的进程进行信息交换。而传输层提供是在两个终端的进程之间数据传输服务(Process-to-Process Delivery Service)。传输层的硬件组成部分,和应用层一样依然是两个终端设备,软件部分是传输层协议,如,UDP 和 TCP。

传输层位于应用层和网络层之间。它给应用层提供数据传输服务,同时,它利用了网络层提供的服务。虽然网络层的 IP (Internet Protocol)协议提供的是尽力传递服务(Best-Effort Delivery Service),也就是说网络层提供的是不可靠的数据传输,但是传输层自身可以通过相关的算法,从而实现可靠的数据传输服务。

传输层提供的服务有:

  • 数据传输。
  • 错误检查。
  • 可靠数据传输。数据的正确性和有序性。
  • 拥塞控制。

传输层主要有 TCP 和 UDP 两个协议,不同的协议提供不同的服务,适用于不同的应用场景。其中,TCP 协议提供的是可靠传输,它包含了上面所有的服务。而 UDP 协议提供的是不可靠传输,包含部分服务,即数据传输和错误检查。

传输层是如何工作的

传输层发送数据的过程:

  • 客户端进程组装应用层报文
  • 进程根据传输层协议,创建相应的 Socket。
  • 进程将应用层消息传给 Socket。
  • Socket 将应用层报文(Message)分成多份,加上传输层报文头。封装成传输层报文段(Segment)传递给网络层。

传输层接收数据的过程:

  • 网络层将组装好的报文段传给传输层。
  • 传输层接收到报文段,根据报文段的头部信息中的目标端口,将报文段传给指定的 Socket。
  • Socket 收集到所有的报文段后,将报文段转换为应用层报文。
  • 进程读取 Socket 中的应用层报文。

上述过程涉及到的一些重要的概念,接下来进行解释。

进程

在操作系统中,一个运行的程序称为一个进程。进程是分配计算机资源的最小单元。网络通信宏观上是两个可计算的终端设备之间的通信,微观上是两个进程之间的通信。

端口

端口(Port Number)一个逻辑的实体,它用于在终端设备进行网络通信时标识一个进程。一个进程可以绑定多个端口。一个端口只能属于一个进程。

网络套接字 (Network Socket)

Socket 是一个软件组件。它帮助计算机程序连接本地网络或者广域网。Socket 为进程打开网络连接,允许进程通过网络读写数据。Socket 是进程间网络通信的一个终端。Socket 是连接应用层和网络层的大门。

一个 Socket 有三个部分组成:传输层协议,IP 地址,端口。Socket 绑定了一个具体的端口,运输层通过端口知道把报文段传送给哪个进程。

UDP 协议

UDP 协议的数据传输服务有以下特征:

  • 不可靠数据传输
  • 无连接
  • 最大网速传输
  • 更小的报文头部

UDP 协议使用使用起来更简单,不需要三次握手建立连接,没有拥塞控制,简单的报文格式等。如果不需要严格的可靠数据传输,允许部分数据丢失,可以考虑使用 UDP 协议。如,应用层协议 DNS 就是使用 UDP。

UDP 报文段结构

Source_port  Dest_port
Length Checksum
(Application data)

UDP 报文段头部共占8字节。由4个字段组成,每个字段2个字节。

Source port:表示客户端进程端口。

Dest port:表示服务端进程端口。

Length:表示报文段的头部和数据的总字节数。

Checksum:用来检查报文段是否出现错误。

TCP 协议

介绍 TCP

TCP 协议有以下特点:

  • 可靠的数据传输
  • 面向连接

TCP 报文段格式如下图所示:

TCP 报文段头部共占20个字节(Options为空时)。其中

Source port,Dest port,checksum 和 UDP 协议类似。

Sequence number 和 Acknowledgement number 用来实现可靠数据传输服务。

Header length 用来表示报文头部的长度,当 Options 为空时,长度为20。

Flag field 包含6个bit。其中 ACK bit 表示应答客户端是否成功接收,RST,SYN,FIN 用于连接设置。

Receive window 用于流控制。

TCP 连接管理

客户端进程和服务端进程建立 TCP 连接的过程:三次握手(Three-Way Handshake)

  • 客户端发送一个特殊的 TCP 报文段(SYN segment),请求建立连接。这个特殊的报文段没有应用层数据。报文段头部设置为:SYN bit 设为1;随机设置一个initial sequence number(client_isn)。
  • 服务端收到 TCP SYN 报文段。响应给客户端一个 TCP 报文段,这个响应的报文段也没有应用层数据,报文段头部设置为:SYN bit 设为1;acknowledgement number 设为 client_isn + 1;设置一个initial sequence number(server_isn)。
  • 客户端收到 SYNACK 报文段。分配连接的缓存和变量。然后发送一个 TCP 报文段给服务端,表示收到服务端的响应。这个报文段同样没有应用层数据,报文段头部设置为:SYN bit 设置为0;acknowledgement number 设置为 server_isn + 1;设置 sequence number 为 client_isn + 1。

为什么建立 TCP 连接需要三次握手?

三次握手为了确定双方都准备好了,确保可以正常通信了。

关闭 TCP 连接的过程:四次挥手

  • 客户端请求关闭 TCP 连接。发送一个特殊的报文段,报文段头部设置为: FIN bit 设为1。
  • 服务端响应客户端请求。
  • 服务端确认可以关闭TCP请求后,发送关闭 TCP 请求。发送一个特殊的报文段,报文头部设置为:FIN bit 设为1.
  • 客户端响应服务端请求。

通过四次通信后,客户端和服务端可以关闭 TCP 连接,释放 TCP 连接资源,如缓存和变量。

可靠数据传输的实现原理

可靠的数据传输服务要保证服务端接收到的数据有以下特征:

  • 没有数据错误
  • 没有数据缺少
  • 没有数据重复
  • 正确的顺序

解决以上问题的方法

  • 解决数据错误。通过报文头 checksum 字段的错误校验和错误重发机制,确保没有数据错误。
  • 解决数据缺少。通过报文头 acknowledgement number 字段和超时重发机制,确保没有数据缺少。
  • 解决数据重复。通过报文头 sequence number 字段,确保没有重复的数据。
  • 正确的顺序。通过报文头 sequence number 字段,确保数据的顺序正确。

具体细节没有展开,有兴趣可以阅读参考资料中的书籍。

流控制的实现原理

流控制就是控制 TCP 报文发送的速率。它的实现是通过客户端和服务端定义的相关变量来控制的。具体的实现原理如下。

服务端

TCP 连接建立后,服务端分配 TCP 连接缓存,定义 RcvBuffer 变量表示缓存的大小,应用进程读取缓存中的数据。定义两个变量:

LastByteRcvd:网络达到的最后一个字节数。

LastByteRead:应用进程读取的最后一个字节数。

TCP 不允许数据溢出分配的缓存。所以必须保证 LastByteRcvd - LastByteRead <= RcvBuffer

客户端

客户端为了不使服务端的缓存溢出,会根据服务端缓存剩余空间大小,控制发送数据的速度。

客户端定义了一个接受窗口(Receive Window)变量 rwnd。这个变量动态变化的,它等于服务端缓存剩余空间的大小。LastByteSent 表示最后发送的一个字节,它对应服务端的LastByteRcvd。LastByteAcked 表示最后一个应答的字节,它对应服务端的 LastByteRead。变量之间的关系为:

rwnd = RcvBuffer - (LastByteSent - LastByteAcked)

TCP 连接成功后,服务端会返回它的缓存大小给客户端,客户端初始化自己的接收窗口变量 rwnd = RcvBuffer。然后客户端根据发送和应答的情况动态改变接收窗口变量大小。当 rwnd=0 时,表示服务端的缓存已经满了,客户端则停止发送 TCP 数据。

拥塞控制的实现原理

拥塞控制的实现利用了 TCP 的流控制,当拥塞发生时,通过减少客户端的发送 TCP 报文的速率,从而减少网络的拥塞。一般通过是否丢包来判断网络是否拥塞。如何避免拥塞?如何控制客户端的速率更合理?这就是拥塞控制算法需要解决的问题。

造成网络拥塞的原因:

  • 路由器排队延迟。数据包到达路由器的速度接近链路容量。
  • 不必要的数据包重发。大量的重复的数据包在网络中传播,占用了链路的带宽。
  • 丢包。如果一个数据包在第n个路由器被丢弃了,那么这个数据包需要重新在1~n的路由器路径上传递。可以给一个优先权,已经在经过了许多路由器的数据包优先通过路由器。

拥塞控制的方法:

  • 端到端拥塞控制(End-to-End Congestion Control)。如果一个 TCP 报文段丢失,表示网络出现拥塞,TCP 自动降低(流控制)接受窗口大小。
  • 网络协助拥塞控制(Network-assisted Congestion Control)。网络出现拥塞,路由器直接反馈给客户端。

拥塞控制算法

  • 慢热启动(Slow Start)。TCP 开始传输的初始速率很低,然后以指数增长,直到出现丢包后停止增长,速率变为当前速度的一半。
  • 拥塞避免(Congestion Avoidance)。当第一次丢包发生后,由慢热启动状态转为拥塞避免状态,传输速率由原来的指数增长,变为线性增长。
  • 快速恢复(Fast Recovery)。
    • TCP Tahoe. 如果在拥塞避免的状态下(即线性增长)再次发生丢包。重新回到慢热启动状态,传输速度设为初始速度。
    • TCP Reno. 如果在拥塞避免的状态下(即线性增长)再次发生丢包。传输速度回到拥塞避免状态的初始速度。

通过拥塞控制算法,最终所有的连接会平均分配链路带宽,它们的传输速度会在平均线上下震荡,所有TCP 连接公平的使用网络。

TCP 协议和 UDP 协议的区别

  1. TCP 是面向连接(三次握手),UDP 是无连接的。
  2. TCP 提供可靠数据传输服务,UDP 提供不可靠传输。
  3. TCP 有拥塞控制(传输速度根据丢包情况调整),UDP 最大速度传输。
  4. TCP 报文头 20 字节,UDP 报文头 8 字节

References

[1] Computer Networking: A Top-Down Approach, by Jim Kurose

[2] Socket Definition

本文主要探究计算机网络的应用层,我们先介绍应用层的基本概念,然后逐一的介绍常见的应用层协议。

应用层的基本概念

应用层是网络协议栈中最上的一层,也是网络通信的第一层,它提供了让两个终端设备进行信息交换的服务。它定义了信息交换的格式,然后把定义好的信息交给它下面一层的传输层去传输。

应用层是由应用层的硬件和软件组成。硬件主要是终端设备,如手机、个人电脑、服务器等。软件主要是应用层网络协议,如 HTTP、DNS 等。应用层协议是给应用程序提供网络通信的基础,一个终端设备中应用程序通过应用层协议发送网络请求,另一个终端设备接收到请求,并通过应用层协议响应请求。其中,发送请求的一端称为客户端,响应请求的一端称为服务端。

网络通信实际上是两个终端设备上的应用程序进行通信,操作系统中一个运行的应用程序称为进程,网络通信也称为进程通信

开发一个网络应用程序,首先,我们需要根据需求选择一个网络应用架构,常见的架构有 CS 架构(Client-Server Architecture)和 P2P 架构 (Peer-to-Peer Architecture)。然后选择一个合适的应用层协议,如 HTTP,FTP等。

  • CS 架构。它有一个一直开启、一直提供服务的主机,称为服务器,其它请求它的主机称为客户机。它的主要特点:客户端之间不直接进行通信,服务器有一个固定的 IP 地址,所有的通信都是在客户端与服务器之间进行。常见的 CS 架构应用有:Web 应用,文件传输,远程登录,和 电子邮件等。

  • P2P 架构。任何两个主机直接可以直接进行通信,这一对主机称为 Peers。提供服务的称为服务器,请求服务的称为客户机。任何一台主机既可以作为服务端,又可以作为客户端。常见的 P2P 架构应用有:文件分享应用,对等下载加速应用迅雷,和网络电话视频应用如 Skype。

  • 混合架构,应用程序既使用 CS 架构,也使用 P2P 架构。如即时消息软件中,服务器用于记录用户的IP地址和相关信息,用户与用户之间直接进行通信。

不同的架构采用了不同的应用层协议,不同的应用层协议使用不同的传输层协议提供的传输服务。下面列举了一些常见的应用采用的网络架构和网络协议。

应用 应用架构 应用层协议 底层传输层协议
电子邮件 CS SMTP TCP
远程终端登录 CS Telnet TCP
Web CS HTTP TCP
文件传输 CS FTP TCP
流媒体 CS HTTP TCP
网络电话视频 P2P SIP, RTP, or Proprietary UDP or TCP
文件分享 P2P BitTorrent TCP

通过这个小节,我们了解了应用层的基本概念,对应用层有了一个大致的了解。接下来,我们将介绍一些常见的应用层协议。

Web 应用和 HTTP 协议


介绍 HTTP

介绍 HTTP 之前,我们先了解一下 World Wide Web 也称 Web。它是世界上使用最广泛的网络应用之一。它是一个信息系统,它提供文件和其它 web 资源的访问服务,所有的资源文件通过 URL(Uniform Resource Locator)来定位。在浏览器输入一个网站的 URL 就可以访问这个网站的资源文件。Web 应用采用的是 CS 架构和 HTTP 协议。

HTTP 协议(HyperText Transfer Protocol),它定义了网络通信中消息的结构,以及客户端和服务端如何交换消息,消息可以称为 HTTP 报文(HTTP Message)。HTTP 网络通信由客户端应用程序和服务端应用程序构成,客户端应用程序为 Web 浏览器,服务端应用程序为 Web 服务器。HTTP 通信的过程是:浏览器通过 URL 指定要访问的资源,然后发送 HTTP 请求给服务器,服务器收到请求后,响应 HTTP 请求。浏览器收到的服务器的响应信息后,渲染该资源文件。

HTTP 报文格式

HTTP 请求报文格式

(Request Line) method URL Version
(Header Lines) header_field_name: value
header_field_name: value
...
(Entity Body) ...

例子

GET /somedir/page.html HTTP/1.1
HOST: www.someschool.edu
Connection: close
User-agent: Mozilla/5.0
Accept-language: en
(data data ...)

字段说明:

请求行(Request Line)中定义了 HTTP 请求的关键参数。其中 Method 字段表示请求的方式,常用的请求方式为GET,POST。URL 字段用来定位资源,Version 字段用来说明当前使用的协议版本。

头部行(Header Lines)中定义了可选的参数,用来辅助 HTTP 请求。

数据域(Entity Body) 用来传输数据。

HTTP 响应报文格式

(Status Line)  version status_code phrase
(Header Lines) header_field_name: value
header_field_name: value
...
(Entity Body) ...

例子

HTTP/1.1 200 OK
Connection: close
Date: Wed, 12 Aug 2019 12:00:01 GMT
Server: Apache/2.2.3
Last-Modified: Wed, 12 Aug 2019 9:11:03 GMT
Content-Length: 6821
Content-Type: text/html
(data data ...)

字段说明:

状态行(Status Line)定义了响应报文的关键参数。其中 Version 用来说明当前使用的协议版本,Status Code 表示请求结果的状态码,phrase 为状态码的说明。

头部行(Header Lines)中定义了可选的参数,用来辅助 HTTP 响应。

数据域(Entity Body) 用来传输数据。响应的数据一般是 HTML 文本,或者 JSON 文本。

常见的状态码

  • 200 OK:请求成功。
  • 301 Moved Permanently:资源位置永久移动,请求会自动重定向到资源新的 URL。
  • 400 Bad Request:错误的请求。
  • 404 Not Found:请求的资源不存在服务器中。
  • 505 HTTP Version Not Supported:HTTP 协议版本不支持。

HTTP 服务器是无状态的,这个设计简化了服务器,允许开发者开发一个高性能的 Web 服务器,服务器可以同时处理上千的 TCP 连接。但是一个网站往往想要区分用户,这样可以限制用户的接入权限,以及记录用户的行为等。为了达到这个目的,HTTP 可以使用 cookie 来追踪用户。

Cookie 是 HTTP 报文中头部中的一个属性,使用 Cookie 由四个部分组成:

  • HTTP 响应报文的头部 (header lines)字段 Set-Cookie 设置 cookie 。
  • HTTP 请求报文的头部字段 Cookie 携带用户的 cookie。
  • 一个 Cookie 文件保存在用户终端,由浏览器管理。
  • 后端数据库保存用户 Cookie。

浏览器每次请求都会携带 Cookie 发送给服务器,服务器可以根据 Cookie 来追踪用户的行为,分析数据,从而优化网站的功能。

Web Cache

Web 缓存服务器 (Web Cache)也称代理服务器,Web Cache 可以缓存静态资源在本地,而不用请求 Web 服务器。

一个机构或公司使用局域网 Web 缓存服务器,可以减少客户端 HTTP 请求的响应时间,也可以减少机构接入网络的带宽。

DNS 协议


介绍 DNS

网络中服务器是通过 IP 地址来识别的, IP 地址是由4个十进制的数字组成如121.7.106.83,这样的地址不方便记忆。DNS (Domain Name System)可以为 Web 服务器提供一个有字母和数字组成的域名 ,如 google.com。

DNS 是一个实现在多个 DNS 服务器的分布式数据库。一个应用层协议允许去查询分布式数据库。它提供了将域名转换为 IP 地址的服务。

浏览器通过服务器的域名获取 IP 地址的过程

  • 查询本地缓存。浏览器先检查浏览器本地缓存中是否有该域名,如果没有,检查电脑的 DNS 缓存中是否有该域名。
  • 查询 DNS 服务器。如果本地缓存没有找到,浏览器通过发送 DNS 查询请求给 DNS 服务器,DNS 接收到请求,返回该域名的 IP 地址。浏览器获得该网站的 IP 地址。(为了便于理解,这里简化了对 DNS 服务器的访问,实际会请求多个 DNS 服务器,下面会详细说明)

为什么浏览器知道了域名,还需要 Web 服务器的 IP 地址?

浏览器是客户端进程,Web 服务器是服务端的一个进程,在操作系统中进程之间的通信是通过 Socket 完成,每个进程都有唯一对应的 Socket,Socket 连接应用层和传输层桥梁。因为 Socket 通信需要的是 IP 地址建立 TCP 连接,所以浏览器需要知道 Web 服务器的 IP 地址。不过查询 IP 地址的过程,是自动地快速地进行的,用户是无感的。

DNS 提供地服务

  • Web 服务器别名。
  • 邮件服务器别名。
  • 负载分配。一个域名关联一组 IP 地址,多个服务器依次处理 HTTP 请求,从而减少了单个服务器的压力。

DNS 层级结构

DNS 服务器是分布在世界各地的,是有层级关系的。三层结构如下:

  • 第一层:根 DNS 服务器 (Root DNS Servers)管理下一层顶级域名 DNS 服务器的地址。

  • 第二层:顶级域名 DNS 服务器(Top-Level Domain (TLD) DNS Servers)管理下一层权威域名 DNS 服务器的地址。一般的顶级域名如 .com、 .edu、 .gov、 .net等。

  • 第三层:权威域名服务器 (authoritative DNS servers)记录了组织机构、公司的所有域名对应的 IP 地址。如 *.baidu.com(www.baidu.com, baike.baidu.com, news.baidu.com)

通过循环查询 DNS 服务器,得到一个域名对应的 IP 地址的过程, 如 cs.umass.edu

  • 客户端请求 <本地 DNS 服务器>,本地 DNS 服务器检查缓存中是否有 cs.umass.edu 对应的 IP 地址。如果有就返回,没有就进行到下一步。
  • 本地 DNS 服务器请求<根 DNS 服务器>,查询 edu 顶级域名服务器 IP 地址。
  • 本地 DNS 服务器请求<顶级域名 DNS 服务器>,查询 umass.edu 的权威域名服务器的 IP 地址。
  • 本地 DNS 服务器请求<权威域名服务器>,查询 cs.umass.edu 对应的 IP 地址。
  • 本地 DNS 服务器最终得到了cs.umass.edu 的 IP 地址,并返回给客户端。

DNS 记录

DNS 分布式数据存储的是 Resource Records (RRs)

一个记录有四个字段(Name, Value, Type, TTL)

TTL 表示域名在 本地 DNS 服务器缓存的时间。

不同的类型表示不同的功能,常见的类型有:

Type=A,表示域名映射到 IP 地址。如(bar.foo.com, 145.37.93.126, A)

Type=CNAME, 表示权威域名的别名。如(foo.com, www.foo.com, CNAME)

Type=MX,表示权威域名的邮箱服务别名。如(foo.com, mail.foo.com, MX)

Type=NS,表示域名进一步查询地址。如(foo.com, dns.foo.com, NS)

DNS 报文

DNS 的请求报文和响应报文格式是一致的,由于用的比较少,具体细节,这里不详细展开,有兴趣的朋友可以去查阅相应资料。

CDN 内容分发网络

网络视频需要消耗大量的网络带宽,很多网络视频公司会选择 CDN (Content Distribution Network)服务,来优化用户的体验。

一个 CDN 网络管理很多分布在世界各地的服务器,在每个服务器上复制了视频和其它资源文件的副本,用户请求 CDN,然后 CDN 提供一个离用户客户端距离较近的服务器同响应客户端请求,从而给用户更快更好的网络体验。CDN 的实现是利用了 DNS 拦截和重定向请求功能。

不使用 CDN 可能会出现的问题

  • 每个客户端都请求同一个地区的服务器(数据中心),服务器的带宽是一定的,请求太多造成客户端得到的资源吞吐量下降,会导致视频卡顿。
  • 一个流行的视频会在同一个通信链路上多次传输,浪费网络带宽。
  • 一个数据中心容易出现单点故障,导致整个服务不可用。

CDN 使用的过程

  • 用户访问一个视频的链接,如 http://video.netcinema.com/6Y7B23V
  • 浏览器查询客户端本地缓存是否存在该域名的 IP 地址。如果没有,继续下一步查询。
  • 浏览器请求本地 DNS 服务器,查询 video.netcinema.com 域名的 IP 地址。本地 DNS 服务器检查本地缓存是否存在该域名,不存在,则请求权威 DNS 服务器,查询 video.netcinema.com 的 IP 地址。权威 DNS 服务器发现是 video 开头的域名,则返回 CDN 提供商的权威域名如 a105.kingcdn.com。
  • 本地 DNS 服务器请求权威域名服务器,查询 a105.kingcdn.com 的 IP 地址,CDN 提供商根据客户端的地理位置,最终返回 CDN 系统中的一个 web 服务器 IP 地址。
  • 本地 DNS 服务器把 IP 地址返回给浏览器。
  • 浏览器通过 IP 地址与服务器建立 TCP 连接,发送视频访问请求。web 服务器返回视频内容给浏览器。

CDN 是如何让客户端访问离自己最近的一个服务器

方法一

使用 DNS 服务器响应一个离用户最近的服务器的 IP 地址。DNS 服务器通过查询 IP 位置数据库,获取客户端所在的城市。根据客户端所在的城市选一个最近的一个服务器的 IP 地址返回给客户端。

方法二

使用任播(Anycast)路由选择一个最近的服务器。CDN 分布世界各地的所有 Web 服务器使用同一个 IP 地址。路由器根据最少花费(Lowest Cost)的路由规则,选择一个离客户端最近的服务器。

References

[1] Computer Networking: A Top-Down Approach, by Jim Kurose

[2] World Wide Web - Wikipedia

[3] DNS Explained - How Your Browser Finds Websites

[4] How does Akamai CDN use DNS to allocate closest edge server to client? - Quora

本文主要是为了让大家了解计算机网络,介绍了网络的基本概念,没有涉及具体的网络协议和网络通信的细节。计算机网络概念和专有名词非常多,为了便于理解,我会尽量用一些简单的语言去描述和解释它们。

什么是因特网


因特网的定义

因特网(Internet)是当今世界广泛使用的计算机网络,也称为互联网。它由一系列硬件和软件组成。它为世界各地的网络应用提供服务。

计算机网络(Computer Network)是一个抽象的概念,它定义了网络的逻辑结构。而因特网是一个具体的网络,是一个客观存在的事物。计算机网络,因特网,互联网等词经常相互使用,容易混淆,本文介绍的网络概念统一使用因特网。

因特网的结构

因特网是一个连接着分布在世界各地的亿万个计算设备的计算机网络。这些计算设备有个人电脑,智能手机,平板电脑,电视,手表,汽车等等。在因特网中这些设备称为主机(Host)或者终端(End Systems)。因特网的基本结构如下图所示

从上图可以看出因特网的构成十分复杂,它连接着许许多多的设备。我们可以简单将因特网划分为两种类型,一个是网络的核心,一个是网络的边缘。

网络的核心主要是由许多互相连接的路由器(Router)组成,它构成了网络的骨架,用于网络信息的传输。而网络的边缘主要是由一个调制解调器(Modem)俗称为猫、一个或多个路由器、交换机(Link-layer switch)和许多终端设备连接在一起,它们构成了一个局域网。其中调制解调器负责连接上因特网,路由器和交换机是用来组建和扩展局域网。局域网中连接着调制解调器的路由器连上了网络,其它连接到这个路由器的设备都可以上网。网络的边缘主要是组建局域网,让局域网内的终端设备可以连接网络。

网络按规模大小可以进行如下分类:

  • 局域网 (Local Area Networks, LAN),如一个家庭,一个公司,一个学校的网络都可以看作是一个局域网。
  • 城域网(Metropolitan Area Network, MAN),一个城市范围内所建立的网络。
  • 广域网(Wide Area Network, WAN),一个国家或一个洲范围内所建立的网络。

通过本小节,你已经大致了解了什么是因特网,为了更加深入的了解因特网的组成结构和它是如何工作的,我们接下来会进一步地讲诉这些内容,以及常见的网络安全问题。

因特网组成

上面已经提到因特网是由一些列硬件和软件组件构成。硬件部分主要有:连接网络的物理媒介、网络设备、和终端设备。软件部分表示的就是网络协议。网络协议规定了网络信息的格式和信息传播的规则。

网路硬件

网络设备:路由器,交换机,调制解调器,手机信号塔等。

终端设备:个人电脑,智能手机,平板电脑,服务器等。

网络连接的物理媒介:

  • 有线传输
    • 双绞线 (Twisted-Pair Copper Wire)。最早用在固定电话网络。 现在常用于局域网的网络接入。它可提供高达10G比特每秒的网络传播速度。
    • 同轴电缆(Coaxial Cable)。常用于有线电视系统,最近有线电视系统也可以提供数十M比特每秒的网络接入。
    • 光纤(Fiber Optics)。它具有很高的传播速度,高达数100G比特每秒。也有很低的信号衰减和抗干扰能力,适合长距离信号传播。如今的因特网的骨架一般都是用光纤去组建。
  • 无线传输
    • 地面无线电波(Terrestrial Radio Channels)
    • 卫星无线电波(Satellite Radio Channels)

网络协议

为了理解网络协议,我们先要知道网络协议是什么?以及它的结构是怎样的?

网络协议是一个网络系统的规则,允许两个或多个终端去交流信息,无论它们采用什么物理媒介进行通信。它定义了传播的信息的数据格式,以及信息传播的规则。因特网有中应用了很多协议,一个协议可能由软件实现,硬件实现,或者软件硬件结合实现。

因特网是一个十分庞大和复杂的系统,一个复杂的系统要高效有序的工作,需要合理的组织它的结构。因特网的协议使用分层结构,每一层执行具体的任务,提供相应的服务,上一层可以使用下一层提供的功能服务。分层的好处就是可以轻松的改变某一个协议的实现,只要它提供相同的服务给上一层,和使用下一层提供相同的服务,当一个协议的实现发生改变,整个系统其它的部分不需要改变。对于大型的复杂的系统,它是需要持续不断的更新的,而分层结构有利与系统的持续更新,所以分层十分有必要的。

OSI 参考模型

在 1970s,国际标准化组织(International Organization for Standardization,ISO)提出网络分为七层称为,开放系统互联模型(Open Systems Interconnection,OSI) 。这七层分别为:应用层、表现层、会话层、传输层、网络层、数据链路层、物理层。其中五层和五层协议名称和功能相同,其它两个表现层和会话层是五层协议没有的。这两层的含义如下:

  • 表现层(Presentation Layer)。提供翻译和转换应用层的数据的服务,它包括数据的压缩,加密,数据描述。这一层存在是因为考虑到不同的电脑的数据表示和存储的格式可能不同,需要进行格式转换。
  • 会话层(Session Layer)。提供对数据交换的限定和同步服务。它包括构建一个检查点和恢复策略。
五层网络协议

五层网络协议,从上到下分别为:应用层,传输层,网络层,链路层,物理层。

应用层(Application Layer)协议是指分布世界的终端设备,一个终端的应用程序使用协议去与另一个终端应用程序交换信息。常见的应用层协议有:HTTP,SMTP,FTP,DNS等。应用层传播的信息称为消息(Message)。

传输层(Transport Layer)协议负责在两个终端应用之间传输应用层的消息。常见的传输层协议有TCP,UDP等。传输层传播的信息称为报文段(Segment)。

网络层(Network Layer)协议负责将数据报从一个主机运送到另一个主机。常见的网络层协议有 IP 协议,以及路由协议。网络层传播的信息称为数据报(Datagram)。

链路层(Link Layer)协议负责将上一层的数据报封装帧格式,在一条链路上传播。链路层协议有:Ethernet,WiFi。链路层传播的信息称为帧(Frame)。

物理层(Physical Layer)负责将上一层的帧封装成比特流在两个节点之间传输。物理层传播的信息称为比特(Bit)。

五层协议的基本工作原理是,两个终端设备要进行数据交流,在一个终端发送应用层的请求,另一端接收到请求并做出相应的回应。应用层的交流是网络通信最终要达成的交流目标,但是仅靠应用层完成不了整个交流的任务。实际上,应用层做好了自己的任务,把剩余的任务交给运输层去完成;运输层完成了自己的任务,把剩余的任务交给网络层;依次类推到物理层,依靠每一层的努力,最终实现了两个终端交流的目的。网络分层的通信结构图如下

上图是一个简化的网络模型,其中一个堆栈表示一个网络设备,为什么在中间的部分只有三层结构,因为在网络的核心负责运送消息,不需要进行通信交流。而网络的边缘即两个终端是进行交流的目标主体。

为什么每一层都有不同的传播信息的名称?实际上,我们知道网络通信最终的目的是完成两个终端之间的通信,也可以说是最上层应用层的通信,而上一层的通信需要依靠下一层提供的服务。在网络通信中,每一层都都有自己的协议,定义了不同大小的传播数据单元,由于每一层传播信息单元的最大数据长度不同,每一层可能需要将上一层的数据切分成多个小段,每一个小段加上当前层的协议内容信息称为头部(Header),每一层的数据格式都是头部加数据域(Data)组成。所以,每一层根据自己协议的规定和职责,组装了自己的数据格式,不同的数据格式则需要不同的名称。

网络通信的过程

一个设备需要进行网络通信首先需要接入网络。谁可以提供网络接入呢?互联网服务提供商(Internet Service Provider, ISP)能够为我们提供网络接入。国内现有的网络运营商为:中国电信,中国移动,中国联通。最常见的网络接入服务有:拨号上网、ADSL、CDMA无线上网。

我们接入网络之后,就可以使用网络应用服务,最常见网络应用服务有:web服务(使用浏览器访问网页),发送电子邮件等。

完整的通信过程是,首先,你所在的区域(家庭或者公司)接入 ISP 提供的网络,客户端(手机,电脑)连上网络,设备上的应用程序使用网络协议发送请求,通过网络的数据传播,提供服务的终端(服务器)上的应用程序接受到请求,并使用网络协议响应请求。

网络安全

网络给我们的生活带来了很多便利,但在使用网络的同时,我们也可能收到网络的攻击。这些网络攻击可能会伤害我们的电脑,窃取我们的隐私信息,以及使服务器无法提供服务等。

常见的安全攻击有

  • 恶意软件(Malware)。通过网络将恶意软件安装到你的电脑中,感染你的电脑。从而删除你的文件,安装间谍软件收集你的隐私信息。常见的恶意软件有:病毒软件、蠕虫软件。
  • 拒绝服务攻击(Denial-of-service (DoS) Attack),大量的访问你的服务器,使服务器无法提供正常的服务。
  • 数据嗅探(Packet Sniffer),监听和保存你的设备发送的网络数据包,从中分析出你的敏感数据。如你的密码,你的交易信息,你的个人隐私信息等。
  • IP欺骗(IP Spoofing),冒充一个网址,从而获取你在该网站的登录用户名和密码等。

References

[1] Computer Networking: A Top-Down Approach, by Jim Kurose

[2] Internet - Wikipedia

[3] Communication Protocol - Wikipedia

[4] 五层因特网协议栈

Background

I want to use Swagger with Spring Boot, but the Swagger-UI can’t work. Following it’s my code.

pom.xml

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
</parent>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger2</artifactId>
<version>2.9.2</version>
</dependency>
<dependency>
<groupId>io.springfox</groupId>
<artifactId>springfox-swagger-ui</artifactId>
<version>2.9.2</version>
</dependency>
</dependencies>

AppConfig.java

@Configuration
@EnableSwagger2
public class SpringFoxConfig
{
@Bean
public Docket api()
{
return new Docket(DocumentationType.SWAGGER_2)
.select()
.apis(RequestHandlerSelectors.any())
.paths(PathSelectors.any())
.build();
}
}

Error Info

When I visited http://localhost:8080/swagger-ui.html, occur following error tips.

Solution

make sure your swagger configuration is under your spring boot application which can be scanned.
and then it solved.

Reason

My config file doesn’t scan by spring boot. It leads to the required bean is not exist.

References

https://github.com/springfox/springfox/issues/1996

Background

I use mvn spring-boot:run command to run my spring boot project.

Error Info

[ERROR] No plugin found for prefix 'spring-boot' in the current project and in the plugin groups [org.apache.maven.plugins, org.codehaus.mojo] available from the repositories [local (D:\Repositories\mavenRepo), central (https://
repo.maven.apache.org/maven2)] -> [Help 1]
[ERROR]
[ERROR] To see the full stack trace of the errors, re-run Maven with the -e switch.
[ERROR] Re-run Maven using the -X switch to enable full debug logging.
[ERROR]
[ERROR] For more information about the errors and possible solutions, please read the following articles:
[ERROR] [Help 1] http://cwiki.apache.org/confluence/display/MAVEN/NoPluginFoundForPrefixException

Solution

Make sure your project pom.xml exists in your terminal’s working directory when you run the mvn spring-boot:run command. The basic configurations for the pom.xml file to run a spring boot project are shown below.

pom.xml

<parent>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-parent</artifactId>
<version>2.1.6.RELEASE</version>
</parent>

<dependencies>
<dependency>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-starter-web</artifactId>
</dependency>
</dependencies>

<build>
<plugins>
<!-- run $ mvn package, generating an executable jar -->
<plugin>
<groupId>org.springframework.boot</groupId>
<artifactId>spring-boot-maven-plugin</artifactId>
</plugin>
</plugins>
</build>

Reason

I run the mvn spring-boot:run command not in my project root directory.

Reference

https://stackoverflow.com/questions/30855864/maven-no-plugin-found-for-prefix-spring-boot-in-the-current-project-and-in-th

为了探究操作系统的工作原理。我们先要知道它是什么,它的作用,以及它的组成结构。然后我们解释为什么需要操作系统。最后,我们开始探究操作系统的工作原理,它是如何实现这些功能的。

什么是操作系统


操作系统的定义

操作系统是一个一直运行在计算机中的程序。它管理着计算机的硬件和软件资源,提供一些服务给计算机的程序。为了更好的理解操作系统,我们可以把它对比一个政府组织,它作用的与政府组织相类似。一个政府组织,它不是为了自己而运作,而是为了给百姓提供服务。操作系统它提供了一个环境,让程序可以在操作系统中运行。


操作系统的功能

  • 用户接口。如用户图形界面,终端等。
  • 程序的执行。
  • I/O 操作。
  • 文件系统操作
  • 通信。
  • 错误侦探。
  • 资源分配。如,为程序分配CPU、分配内存。

操作系统的结构

常见的操作系统结构如下。

  • 整体结构 (Monolithic Structure)。结构比较简单,没有清晰的层次和模块划分。这种结构,初期看起来会比较简单。由于耦合度较高,后期就比较难维护,以及容易出现安全问题。
  • 分层结构 (Layered Approach)。系统分为多个层,较低的层的提供一系列方法给较高的层调用。这是一种松耦合的结构,系统中某一个部分改变对其它部分没有很大的影响。另外,这种结构比较易于系统调试。
  • 微核心结构 (Microkernels)。把所有不必要的组件从内核中移除,作为用户层的软件去实现,把内核最小化。这样的结构易于系统扩展,添加新的系统服务不需要修改内核。
  • 组件化结构 (Modules)。内核包含一些核心的组件,其它系统服务模块可以通过动态加载来实现。

现代操作系统一般采用上面的某一种结构。但有的操作系统会采用混合多种不同的结构。大部分现代操作系统都采用一种组件化结构称为 Loadable Kernel Modules (LKMs)。

虽然每个系统的结构各不相同,但它提供的功能大致是相同的。如进程管理,文件管理,设备管理等功能是必要的。每个系统为了实现它要提供的功能,采用一个合适的结构就好。最重要的是把功能很好的实现,以及方便操作系统能够持续的维护和优化。

现代 Linux 系统内核结构采用组件化结构,如图


为什么需要操作系统

操作系统是连接硬件和用户软件的媒介。它对硬件资源进行管理,提供一个让用户软件可以运行的环境,以及给用户提供了用户图形接口(GUI)让用户可以方便使用硬件资源。没有操作系统提供的环境,我们就无法享受各种各样的应用软件带来的便利。


操作系统是如何工作的


操作系统的启动过程

当笔记本电脑按下开机键后,位于电脑主板上的固件 ROM 中的启动程序(Boot Loader)会运行,常见的启动程序有 BIOS 和 UEFI。启动程序会加载操作系统的启动程序,进而把整个操作系统加载到内存中并开始执行操作系统。然后安装驱动程序,创建初始化系统进程,启动必要的服务(如Web服务器,数据库等),最终出现系统登录的页面。


操作系统是如何为用户程序服务的?

操作系统启动成功后,就可以登录系统。用户可以根据自己的需要运行相应的程序,如浏览器,文本编辑器等。

一个程序的运行,需要把可执行文件加载到内存中,需要使用 CPU 去执行。然而,硬件资源(CPU,内存等)是被操作系统所管理的,为了安全和高效,用户程序不能直接使用硬件资源。

操作系统为用户程序提供了一系列的接口,通过调用对应的接口获取相应的服务和资源。这一系列接口称为系统调用 (System Call)接口。

常见的系统调用接口

  • 进程控制。创建子进程,获取进程属性,分配额外内存空间等等。
  • 文件管理。创建和删除文件,打开和关闭文件,读写文件等等。
  • 设备管理。请求连接设备,关闭设备,读写设备等等。

操作系统是如何管理硬件和软件资源的?

为了更高效的使用硬件资源,需要合理的管理和分配资源。操作系统负责给进程分配资源。关于 CPU 的分配,一般采用轮询调度算法(Round-Robin Scheduling),即每个进程依次被 CPU 执行一个小的时间片段。关于内存的分配,一般采用的是虚拟内存,它可以使进程的逻辑内存空间远大于实际的物理内存空间,从而能运行更多的程序,更大程度的使用计算机硬件资源。

除了管理硬件资源,操作系统还要管理软件资源。如何让进程同步,如何解决进程死锁,如何实现文件I/O 等等。由于篇幅原因,这里就不具体展开。以后会单独作为一篇文章去写。


结语

通过了解操作系统是什么,为什么需要操作系统,以及操作系统的工作原理。我们大致了解操作系统的内部结构和实现机制。想要了解更多操作系统相关内容,可以阅读我的参考内容。


References

[1] Silberschatz, A. Operating system concepts 10th [M]. 2018.

[2] Operating system - Wikipedia

写博客这件事,最早是上大学的时候,老师课堂上说让我们写博客,说写博客不仅能够加强对知识的理解,也有利于将来找工作。那时对计算机领域相关东西了解的很少,学得也少,对写博客这件事没什么想法,写博客这件事从脑海中一闪而过了。毕业之后,也常常有写博客的念头。但是,感觉自己没什么可写。或者缺少开始的勇气。

最近,对整个计算机领域技术进行了梳理,对计算机技术有了一个较深的理解。知道自己要学什么、要干什么。同时,学习了很多计算机基础的内容,如组成原理,操作系统和算法。原来看起来很高深、很复杂的算法和实现原理,当你理解了之后,再回头看也就没有那么难。克服对技术的恐惧心理。所以,写博客看起来也不是一件很难的事情了。于是,经过一番折腾把博客搭起来了。接下来就是,写博客了。相信,那也不是一件很难的事!


0%