链路层通信使用的是 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 地址。其过程如下:
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 等等。
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 路由器接收到请求后,通过修改报文的目标地址为局域网地址,修改目标端口为进程的端口,将这个报文转发给内网的主机的一个进程。
网络结构像是一个由多个节点相互连接的图。一个图结构有 N 个节点和 E 条边组成。每一个相邻的节点称为邻居,任意两个连通的节点形成的一条路径。路由算法就是算出任意两个节点之间的最小花费路径(Least-cost path)。
路由算法可以通过很多方式实现,可以将它们进行分类:
集中路由算法,分散路由算法
静态路由算法,动态路由算法
负载敏感算法,负载不敏感的算法
Link-state (LS) 路由算法
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
为了解决这些问题,每个地区可以通过一组路由器构建一个自治系统(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 表示目标主机不可接入。
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 字段和超时重发机制,确保没有数据缺少。
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)
浏览器请求本地 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
在 1970s,国际标准化组织(International Organization for Standardization,ISO)提出网络分为七层称为,开放系统互联模型(Open Systems Interconnection,OSI) 。这七层分别为:应用层、表现层、会话层、传输层、网络层、数据链路层、物理层。其中五层和五层协议名称和功能相同,其它两个表现层和会话层是五层协议没有的。这两层的含义如下:
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.
为了更高效的使用硬件资源,需要合理的管理和分配资源。操作系统负责给进程分配资源。关于 CPU 的分配,一般采用轮询调度算法(Round-Robin Scheduling),即每个进程依次被 CPU 执行一个小的时间片段。关于内存的分配,一般采用的是虚拟内存,它可以使进程的逻辑内存空间远大于实际的物理内存空间,从而能运行更多的程序,更大程度的使用计算机硬件资源。