网络通信协议综述笔记

一、网络协议与网络分层

1. 当想要买一个商品,常规的做法就是打开浏览器,输入购物网站的地址。浏览器就会显示一个页面,它之所以能够显示这个页面,是因为它收到了一段来自HTTP协议的响应。拿考拉海购来举例,格式就像下面这样:

HTTP/1.1 200 OK
Date: Tue, 27 Mar 2018 16:50:26 GMT
Content-Type: text/html;charset=UTF-8
Content-Language: zh-CN

<!DOCTYPE html>
<html>
<head>
<base href="https://pages.kaola.com/" />
<meta charset="utf-8"/> <title>网易考拉3周年主会场</title>

(1)比如先在浏览器里面输入https://www.kaola.com ,这是一个 URL,浏览器只知道名字是“www.kaola.com”,但是不知道具体的地点,所以不知道应该如何访问,于是它打开地址簿去查找,可以使用DNS去查找,还可以使用另一种更加精准的地址查找协议HTTPDNS。无论用哪一种方法查找,最终都会得到这个IP地址:106.114.138.24。

知道了目标地址浏览器就开始打包它的请求,对于普通的浏览请求往往会使用HTTP协议;但是对于购物的请求,往往需要进行加密传输,因而会使用HTTPS协议。无论是什么协议,里面都会写明“要买什么和买多少”,如下图所示:

(2)DNS、HTTP、HTTPS所在的层称为应用层。经过应用层封装后,浏览器会将应用层的包交给下一层去完成,通过socket编程来实现。下一层是传输层,有两种协议,一种是无连接的协议UDP,一种是面向连接的协议TCP。对于支付来说往往使用TCP协议。所谓面向连接就是,TCP会保证这个包能够到达目的地,如果不能到达就会重新发送直至到达。

TCP协议里面会有两个端口,一个是浏览器监听的端口,一个是电商服务器监听的端口。操作系统往往通过端口来判断,它得到的包应该给哪个进程,如下图所示:

(3)传输层封装完毕后,浏览器会将包交给操作系统的网络层。网络层的协议是IP协议。在IP协议里会有源IP地址,即浏览器所在机器的IP地址和目标IP地址,即电商网站所在服务器的IP地址,如下图所示:

(4)知道目标IP地址后,操作系统就要去网关,操作系统在启动时就会被DHCP协议配置IP地址,以及默认网关的IP地址192.168.1.1。操作系统如何将IP地址发给网关呢?在本地通信靠广播,网关会回答它自己的本地地址,这个本地地址就是MAC地址,而广播用的是ARP协议,如下图所示:

于是操作系统将IP包交给了下一层也就是MAC层,网卡再将包发出去。由于这个包里面是有MAC地址的,因而它能够到达网关。网关收到包之后会根据自己的知识,判断下一步应该怎么走。网关往往是一个路由器,到某个IP地址应该怎么走,这个叫作路由表。路由器连接两个局域网,局域网内部可以使用本地MAC地址进行通信

(5)一旦跨越局域网,就需要拿出IP头来,查看目标IP地址,路由器往往是知道去哪的,因为临近的路由器之间也会经常沟通。到哪里应该怎么走,这种沟通的协议称为路由协议,常用的有OSPF和BGP。两个路由器之间是一个局域网,当网络包知道了下一步去哪个路由器,还是要使用局域网内部的MAC地址,通过下一个路由器的MAC地址找到下一个路由器,然后再问下一步的路怎么走,一直到走出最后一个路由器。

最后一个路由器知道这个网络包要去的地方,于是对着某个局域网广播谁是目标IP,目标服务器就会回复一个MAC地址。网络包过关后,通过这个MAC地址就能找到目标服务器。

(6)目标服务器发现MAC地址对上了,取下MAC头来发送给操作系统的网络层,发现IP也对上了,就取下IP头。IP头里会写上一层封装的是TCP协议,然后将其交给传输层即TCP层。在这一层里对于收到的每个包,都会有一个回复的包说明收到了。这个回复的包并非这次下单请求的结果,例如购物是否成功扣了多少钱等,而仅仅是TCP层的一个说明即收到之后的回复。当然这个回复会沿着刚才来的方向走回去,报个平安。

(7)如果过一段时间回复还是没到,发送端的TCP层会重新发送这个包,还是上面的过程,直到收到平安到达的回复。这个重试绝非浏览器重新将下单这个动作重新请求一次,对于浏览器来讲就发送了一次下单请求,TCP层不断自己闷头重试,除非TCP这一层出了问题例如连接断了,才轮到浏览器的应用层重新发送下单请求。当网络包平安到达TCP层之后,TCP头中有目标端口号,通过这个端口号可以找到电商网站的进程(如Tomcat)正在监听这个端口号,将这个包发给电商网站,如下图所示:

(8)电商网站的进程得到HTTP请求的内容,知道了要买东西、买多少。往往一个电商网站最初接待请求的这个Tomcat只是个负载均衡代理,负责统筹处理这个请求,而不是所有的事情都自己做,例如要告诉专门管理订单的进程,登记要买某个商品、买多少,要告诉管理库存的进程库存要减少多少,要告诉支付的进程应该付多少钱等等。

如何告诉相关的进程呢?往往通过RPC调用,就是当告诉管理订单进程的时候,该代理不用关心中间的网络互连问题,会由RPC框架统一处理。RPC框架有很多种,有基于HTTP协议放在HTTP报文里的,有直接封装在TCP报文里的。当代理发现相应的服务器进程都处理完毕,就回复一个HTTPS的包告知下单成功。这个HTTPS的包会像来的时候一样,经过各种路由到达用户电脑,最终进入浏览器显示支付成功。

2. 各层的网络协议如下图所示:

网络为什么要分层?因为网络包的格式很复杂,这个程序也很复杂。复杂的程序都要分层,这是程序设计的要求。比如复杂的电商还会分数据库层、缓存层、Compose层、Controller层和接入层,每一层专注做本层的事情。可以想象一下这个程序的工作过程,如下图所示:

TCP在三次握手时,IP层和 MAC层在做什么呢?当然是TCP发送每一个消息,都会带着IP层和MAC层了,因为TCP每发送一个消息,IP层和MAC层的所有机制都要运行一遍。这里要记住一点:只要是在网络上跑的包,都是完整的,可以有下层没上层,绝对不可能有上层没下层。所以对TCP协议来说,三次握手也好重试也好,只要想发出去包就要有IP层和MAC层,不然是发不出去的。

二、ifconfig命令

3. 关于ifconfig和ip addr的区别,这是一个有关net-tools和iproute2的历史故事。运行一下ip addr应该会输出下面的内容:

root@test:~# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN group default 
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
    inet6 ::1/128 scope host 
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UP group default qlen 1000
    link/ether fa:16:3e:c7:79:75 brd ff:ff:ff:ff:ff:ff
    inet 10.100.122.2/24 brd 10.100.122.255 scope global eth0
       valid_lft forever preferred_lft forever
    inet6 fe80::f816:3eff:fec7:7975/64 scope link 
       valid_lft forever preferred_lft forever

这个命令显示了这台机器上所有的网卡。大部分的网卡都会有一个IP地址,当然这不是必须的,后面会遇到没有IP地址的情况。如上输出的结果,10.100.122.2就是一个IP地址,这个地址被点分隔为四个部分,每个部分8个bit,所以IPV4地址总共是32,这样产生的I地址的数量很快就不够用了,于是就有了IPv6,也就是上面输出结果里面inet6 fe80::f816:3eff:fec7:7975/64,有128位。

IPV4还被分为了5类,如下图所示:

在网络地址中,对于A、B、 C类主要分两部分,前面一部分是网络号,后面一部分是主机号。下面这个表格,详细展示了A、B、C三类地址所能包含的主机的数量:

这里有个尴尬的事情,就是C类地址能包含的最大主机数量实在太少了,只有254个,现在估计一个网吧都不太够用,而B类地址能包含的最大主机数量又太多了,6万多台机器放在一个网络下面,一般的企业基本达不到这个规模,闲着的地址就是浪费。

于是有了一个折中的方式叫作无类型域间选路(CIDR,这种方式打破了原来设计的几类地址的做法,将32位的IP地址一分为二,前面是网络号,后面是主机号,可以用来判断两个IP地址是否在同一个子网内。从哪里分呢?10.100.122.2/24这个IP地址中有一个斜杠,斜杠后面有个数字24,后面24的意思是,32位中,前24位是网络号,后8位是主机号

伴随着CIDR存在的,一个是广播地址10.100.122.255,如果发送这个地址,所有10.100.122网络里的机器都可以收到。另一个是子网掩码255.255.255.0,将子网掩码和IP地址进AND计算,前面三个 255转成二进制都是1,1和任何数值取AND都是原来数值,因而前三个数不变为10.100.122后面一个 0转换成二进制是0,0和任何数值取AND都是0,因而最后一个数变为0,合起来就是10.100.122.0,这就是网络号。将子网掩码和IP地址按位计算AND,就可得到网络号

4. 在日常的工作中,几乎不用划分A 类、B类或者C类,所以时间长了很多人就忘记了这个分类,而只记得CIDR。但是有一点还是要注意,就是公有IP地址和私有IP地址,如下图所示:

表格最右列是私有IP地址段。平时数据中心里、办公室、家里或学校的IP地址,一般都是私有IP地址段,因为这些地址允许组织内部的IT人员自己管理、分配,而且可以重复。而公有IP地址有个组织统一分配,需要去买。表格中的192.168.0.x是最常用的私有IP地址。家里的Wi-Fi对应就会有一个IP地址,一般家里上网设备不会超过256个,所以/24基本就够了。有时候也能见到/16的CIDR,这两种是最常见的。

不需要将十进制转换为二进制32位,就能明显看出192.168.0是网络号,后面是主机号,而整个网络里面的第一个地址192.168.0.1,往往就是这个私有网络的出口地址,例如家里的电脑连接Wi-Fi,Wi-Fi路由器的地址就是192.168.0.1,而192.168.0.255就是广播地址,一旦发送这个地址,整个192.168.0网络里面的所有机器都能收到。

但是也不总都是这样的情况。例如16.158.165.91/22这个CIDR,来求一下这个网络的第一个地址、子网掩码和广播地址。要是上来就写16.158.165.1就错了,/22不是8的整数倍,只能先变成二进制来看,16.158的部分不会动,它占了前16位。中间的165变为二进制为10100101,/22除了前面的16位还剩6位,所以这8位中前6位是网络号,即16.158.<101001>,而<01>.91是机器号。因此第一个地址是16.158.<101001><00>.1,即16.158.164.1;子网掩码是255.255.<111111><00>.0,即255.255.252.0;广播地址为16.158.<101001><11>.255,即16.158.167.255。

这五类地址中,还有一类D类是组播地址。使用这一类地址,属于某个组的机器都能收到,有点类似在公司里大家都加入了一个邮件组,发送邮件后加入这个组的都能收到。组播地址在后面VXLAN协议部分会提到。在上面ip addr命令的输出中,IP地址的后面有个scope,对于eth0这张网卡来说是global,说明这张网卡是可以对外的,可以接收来自各个地方的包;对于lo来说是host,说明这张网卡仅可以供本机相互通信。lo全称是loopback,又称环回接口,往往会被分配到127.0.0.1这个地址,这个地址用于本机通信,经过内核处理后直接返回,不会在任何网络中出现。

5. 在上面ip addr命令输出中,IP地址的上一行是link/ether fa:16:3e:c7:79:75 brd ff:ff:ff:ff:ff:ff,这个被称为MAC地址,是一个网卡的物理地址,用十六进制6个byte表示。MAC地址号称全局唯一,不会有两个网卡有相同的MAC地址,而且网卡自生产出来就带着这个地址。那既然这样,整个互联网的通信全部用MAC地址不就好了?

这样其实是不行的。一个网络包从一个地方传到另一个地方,除了要有确定的地址,还需要有定位功能,而IP地址才是有远程定位功能的,MAC地址更像是身份证,是一个唯一的标识,它的唯一性设计是为了组网的时候,不同的网卡放在一个网络里面时,可以不用担心冲突,从硬件角度保证不同的网卡有不同的标识,就比如人出生有户籍和身份证,但人长大了可能会去其他城市,显然通过身份证和户籍没法找到现在这个人在哪,所以MAC地址只能用来同一局域子网内通信,IP地址用来在多个网络间路由和跨子网通信

再来看上面ip addr命令输出中的<BROADCAST,MULTICAST,UP,LOWER_UP>内容,这个叫做net_device flags,即网络设备的状态标识UP表示网卡处于启动的状态;BROADCAST表示这个网卡有广播地址,可以发送广播包;MULTICAST表示网卡可以发送多播包;LOWER_UP表示L1是启动的,即网线插着

MTU1500是指最大传输单元MT为 1500,这是以太网的默认值,它是二层MAC层的概念。MAC层有MAC的头,以太网规定连MAC头带正文合起来,不允许超过1500个字节,正文里面有IP头、TCP头、HTTP头,如果放不下就需要分片来传输

qdisc pfifo_fast中,qdisc全称是queueing discipline叫排队规则,内核如果需要通过某个网络接口发送数据包,它都需要按照为这个接口配置的qdisc(排队规则)把数据包加入队列。最简单的qdisc是pfifo,它不对进入的数据包做任何处理,数据包采用先入先出的方式通过队列。

pfifo_fast稍微复杂一些,它的队列包括三个波段(band),在每个波段里面使用先进先出规则。三个波段(band)的优先级也不相同。band 0的优先级最高,band 2的最低。如果band 0里有数据包,系统就不会处理band 1里的数据包,band 1和band 2之间也是一样。数据包是按照服务类型(Type of Service,TOS)被分配到三个波段(band)里的。TOS是IP头里的一个字段,代表了当前的包是高优先级还是低优先级的

三、DHCPPXE

6. IP地址并不是随便配的,例如旁边的机器都是192.168.1.x,非得配置一个16.158.23.6,这样包就会发不出去。Linux系统没有那么智能,虽然用肉眼看到那台机器就在旁边,但它则需要根据自己的逻辑进行处理。只要是在网络上跑的包都是完整的,可以有下层没上层,绝对不可能有上层没下层,所以尽管它有自己的源IP地址16.158.23.6,也有目标IP地址192.168.1.6,但是包发不出去是因为MAC层还没填。

自己的MAC地址自己知道,但是目标MAC是不是填192.168.1.6这台机器的MAC地址呢?当然不是。Linux首先会判断,要去的这个地址和自己的网卡是否是同一网段的,只有是一个网段的它才会发送ARP请求获取MAC地址;如果发现不是,Linux默认的逻辑是,如果这是一个跨网段的调用,它便不会直接将包发送到网络上,而是企图将包发送到网关

如果配置了网关的话,Linux会获取网关的MAC地址,然后将包发出去。对于 192.168.1.6这台机器,虽然路过它家门的这个包目标IP是它,但是无奈MAC地址不是它的(是网关的),所以它的网卡是不会把包收进去的。如果没有配置网关,那包压根就发不出去。如果将网关配置为192.168.1.6那也不可能,Linux不会让配置成功的,因为网关要和当前的网络至少一个网卡是同一个网段的,16.158.23.6的网关不该是192.168.1.6。

真正配置网络地址的时候,一定不是直接用Linux命令配置的,而是放在一个配置文件里面,不同系统的配置文件格式不同,但基本就是CIDR、子网掩码、广播地址和网关地址。

如果是数据中心服务器,配置了IP之后一般不能变的,但是如果是大量客户端的机器,就需要有一个自动配置的协议,也就是动态主机配置协议(Dynamic Host Configuration Protocol,DHCP)。有了这个协议网络管理员就轻松多了,他只需要配置一段共享IP地址,每一台新接入的机器都通过DHCP协议,来这个共享IP地址里申请其中一个,然后自动配置好就可以了,等机器用完了再还回去,这样其他的机器也能用。

7. 当一台机器新加入一个网络时啥情况都不知道,只知道自己的MAC地址,所以会先进行广播询问自己被分配的IP地址是什么,这一步称为DHCP Discover。新来的机器使用IP地址0.0.0.0发送了一个广播包,目的IP地址为 255.255.255.255,广播包封装了UDP,UDP封装了BOOTP,其实DHCP是BOOTP的增强版,但是如果去抓包很可能看到的名称还是BOOTP协议。广播包的格式就像下图所示:

如果网络管理员在网络里面配置了DHCP Server的话,它就相当于这些IP的管理员,它立刻能知道来了一个“新人”,这时可以体会MAC地址唯一的重要性了,当一台机器带着自己的MA地址加入一个网络的候,MAC是它唯一的身份,如果连这个都重复了就没办法配置了。只有MAC唯一,DHCP Server才能知道这是一个新人,需要租给它一个IP地址,这个过程称为DHCP Offer。同时,DHCP Server为此客户端保留为它提供的IP地址,从而不会为其他DHCP客户端分配此IP地址。DHCP Offer的格式就像下图所示,里面有给新人分配的地址:

DHCP Server仍然使用广播地址作为目的地址,因为此时请求分配IP的新人还没有自己IP。除此之外,DHCP Server还发送了子网掩码、网关和IP地址租用期等信息,如果有多个DHCP Server,这台新机器会收到多个IP地址,它会选择其中一个DHCP Offer,一般是最先到达的那个,并且会向网络发送一个DHCP Request广播数据包,包中包含该客户端的MAC地址、接受租约中的IP地址、提供此租约的DHCP服务器地址等,并告诉所有DHCP Server它将接受哪一台服务器提供的IP地址,并请求其他DHCP Server撤销它们提供的IP地址,以便提供给下一个IP租用请求者,如下图所示:

此时,由于还没有得到DHCP Server的最后确认,客户端仍然使用0.0.0.0为源IP地址、255.255.255.255为目标地址进行广播,在BOOTP里面接受某DHCP Server分配的IP。DHCP Server接收到客户机的DHCP request后,会广播返回给客户机一个DHCP ACK消息包,表明已经接受客户机的选择,并将这一IP地址的合法租用信息和其他配置信息都放入该广播包发给客户机,欢迎它加入网络大家庭,最终租约达成时还是需要广播一下,让大家都知道。

租期到了,DHCP Server就要将IP收回,如果还要续租的话,不能到了时间再续租,而是要提前一段时间,客户机会在租期过去50%的时候,直接向为其提供IP地址的DHCP Server发送DHCP request消息包,客户机接收到该服务器回应的DHCP ACK消息包,会根据包中所提供的新租期以及其他已经更新的TCP/IP参数,更新自己的配置,这样IP租用更新就完成了。

8. 但是其实DHCP里面隐藏着一个细节,接下来就讲一个有意思的事情:网络管理员不仅能自动分配IP地址,还能帮助客户机自动安装操作系统。数据中心里面的管理员一下子就拿到几百台空机器,一个个安装操作系统会累死,所以管理员希望不仅仅自动分配IP地址,还要自动安装系统。装好系统之后自动分配IP地址,直接启动就能用当然最好了。

其实,这个过程和操作系统启动的过程有点儿像。首先启动BIOS,它只能读取硬盘的MBR启动扇区,将GRUB启动起来;然后将权力交给GRUB,GRUB加载内核、加载作为根文件系统的initramfs文件;然后将权力交给内核;最后内核启动,初始化整个操作系统。那安装操作系统的过程,只能插在BIOS启动之后了,因为没安装系统之前连启动扇区都没有,因而这个过程叫做预启动执行环境(Pre-boot Execution Environment,PXE)。

PXE协议分为客户端和服务器端,由于还没有操作系统,只能先把客户端放在BIOS里面,当计算机启动时,BIOS把PXE客户端调入内存里,就可以连接到服务端做一些操作了。首先PXE客户端自己也需要有个IP地址,因为PXE的客户端启动起来,就可以发送一个DHCP请求,让DHCP Server给它分配一个地址。PXE客户端有了自己的地址,那怎么知道PXE服务器在哪呢?对于其他的协议都好办,例如告诉浏览器要访问的IP地址,或者在配置中告诉它,例如微服务之间的相互调用。但是PXE客户端启动的时候啥都没有,好在DHCP Server除了分配IP地址以外还可以做一些其他的事情,下面是一个DHCP Server的样例配置:

ddns-update-style interim;
ignore client-updates;
allow booting;
allow bootp;
subnet 192.168.1.0 netmask 255.255.255.0
{
option routers 192.168.1.1;
option subnet-mask 255.255.255.0;
option time-offset -18000;
default-lease-time 21600;
max-lease-time 43200;
range dynamic-bootp 192.168.1.240 192.168.1.250;
filename "pxelinux.0";
next-server 192.168.1.180;
}

默认的DHCP Server是需要配置的,无非是配置IP时所需要的IP地址段、子网掩码、网关地址、租期等。如果想使用PXE,则需要配置next-server指向PXE服务器的地址,另外要配置初始启动文件filename,这样PXE客户端启动后发送DHCP请求之后,除了能得到一个IP地址,还可以知道PXE服务器在哪里,也可以知道如何从PXE服务器上下载某个文件,去初始化操作系统

9. 接下来看一下PXE的工作过程:

(1)首先,启动PXE客户端。第一步是通过DHCP协议告诉DHCP Server,机器上啥都没有,DHCP Server便租给它一个IP地址,同时也给它PXE服务器的地址、启动文件pxelinux.0。

(2)其次,PXE客户端知道要去PXE服务器下载这个文件后,就可以初始化机器,于是便开始下载,下载时使用的是TFTP协议,所以PXE服务器上往往还需要有一个TFTP服务器。PXE客户端向TFTP服务器请求下载这个文件,TFTP服务器就将这个文件传给它。

(3)然后,PXE客户端收到这个文件后,就开始执行这个文件。这个文件会指示PXE客户端,向TFTP服务器请求计算机的配置信息pxelinux.cfg,TFTP服务器会给PXE客户端一个配置文件,里面会说内核在哪里、initramfs在哪里,PXE客户端会请求这些文件。

(4)最后,启动Linux内核。一旦启动了操作系统,以后就啥都好办了。

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值