mirror of
https://github.com/cheetahlou/CategoryResourceRepost.git
synced 2025-11-17 22:53:42 +08:00
del
This commit is contained in:
154
极客时间专栏/geek/趣谈网络协议/第一模块 通信协议综述/第1讲 | 为什么要学习网络协议?.md
Normal file
154
极客时间专栏/geek/趣谈网络协议/第一模块 通信协议综述/第1讲 | 为什么要学习网络协议?.md
Normal file
@@ -0,0 +1,154 @@
|
||||
<audio id="audio" title="第1讲 | 为什么要学习网络协议?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/3b/da/3b2bd6909ecb4479e60fa0aa310882da.mp3"></audio>
|
||||
|
||||
《圣经》中有一个通天塔的故事,大致是说,上帝为了阻止人类联合起来,就让人类说不同的语言。人类没法儿沟通,达不成“协议”,通天塔的计划就失败了。
|
||||
|
||||
但是千年以后,有一种叫“程序猿”的物种,敲着一种这个群体通用的语言,连接着全世界所有的人,打造这互联网世界的通天塔。如今的世界,正是因为互联网,才连接在一起。
|
||||
|
||||
当"Hello World!"从显示器打印出来的时候,还记得你激动的心情吗?
|
||||
|
||||
```
|
||||
public class HelloWorld {
|
||||
public static void main(String[] args){
|
||||
System.out.println("Hello World!");
|
||||
}
|
||||
}
|
||||
|
||||
```
|
||||
|
||||
如果你是程序员,一定看得懂上面这一段文字。这是每一个程序员向计算机世界说“你好,世界”的方式。但是,你不一定知道,这段文字也是一种协议,是人类和计算机沟通的协议,**只有通过这种协议,计算机才知道我们想让它做什么。**
|
||||
|
||||
## 协议三要素
|
||||
|
||||
当然,这种协议还是更接近人类语言,机器不能直接读懂,需要进行翻译,翻译的工作教给编译器,也就是程序员常说的compile。这个过程比较复杂,其中的编译原理非常复杂,我在这里不进行详述。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/e8/7d/e823209e795faacdbb9b557750e7d37d.jpg" alt="">
|
||||
|
||||
但是可以看得出,计算机语言作为程序员控制一台计算机工作的协议,具备了协议的三要素。
|
||||
|
||||
<li>
|
||||
**语法**,就是这一段内容要符合一定的规则和格式。例如,括号要成对,结束要使用分号等。
|
||||
</li>
|
||||
<li>
|
||||
**语义**,就是这一段内容要代表某种意义。例如数字减去数字是有意义的,数字减去文本一般来说就没有意义。
|
||||
</li>
|
||||
<li>
|
||||
**顺序**,就是先干啥,后干啥。例如,可以先加上某个数值,然后再减去某个数值。
|
||||
</li>
|
||||
|
||||
会了计算机语言,你就能够教给一台计算机完成你的工作了。恭喜你,入门了!
|
||||
|
||||
但是,要想打造互联网世界的通天塔,只教给一台机器做什么是不够的,你需要学会教给一大片机器做什么。这就需要网络协议。**只有通过网络协议,才能使一大片机器互相协作、共同完成一件事。**
|
||||
|
||||
这个时候,你可能会问,网络协议长啥样,这么神奇,能干成啥事?我先拿一个简单的例子,让你尝尝鲜,然后再讲一个大事。
|
||||
|
||||
当你想要买一个商品,常规的做法就是打开浏览器,输入购物网站的地址。浏览器就会给你显示一个缤纷多彩的页面。
|
||||
|
||||
那你有没有深入思考过,浏览器是如何做到这件事情的?它之所以能够显示缤纷多彩的页面,是因为它收到了一段来自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>
|
||||
|
||||
```
|
||||
|
||||
这符合协议的三要素吗?我带你来看一下。
|
||||
|
||||
首先,符合语法,也就是说,只有按照上面那个格式来,浏览器才认。例如,上来是**状态**,然后是**首部**,然后是**内容**。
|
||||
|
||||
第二,符合语义,就是要按照约定的意思来。例如,状态200,表述的意思是网页成功返回。如果不成功,就是我们常见的“404”。
|
||||
|
||||
第三,符合顺序,你一点浏览器,就是发送出一个HTTP请求,然后才有上面那一串HTTP返回的东西。
|
||||
|
||||
浏览器显然按照协议商定好的做了,最后一个五彩缤纷的页面就出现在你面前了。
|
||||
|
||||
## 我们常用的网络协议有哪些?
|
||||
|
||||
接下来揭秘我要说的大事情,“双十一”。这和我们要讲的网络协议有什么关系呢?
|
||||
|
||||
在经济学领域,有个伦纳德·里德(Leonard E. Read)创作的《铅笔的故事》。这个故事通过一个铅笔的诞生过程,来讲述复杂的经济学理论。这里,我也用一个下单的过程,看看互联网世界的运行过程中,都使用了哪些网络协议。
|
||||
|
||||
你先在浏览器里面输入 [https://www.kaola.com](https://www.kaola.com) ,这是一个**URL**。浏览器只知道名字是“www.kaola.com”,但是不知道具体的地点,所以不知道应该如何访问。于是,它打开地址簿去查找。可以使用一般的地址簿协议**DNS**去查找,还可以使用另一种更加精准的地址簿查找协议**HTTPDNS**。
|
||||
|
||||
无论用哪一种方法查找,最终都会得到这个地址:106.114.138.24。这个是**IP**地址,是互联网世界的“门牌号”。
|
||||
|
||||
知道了目标地址,浏览器就开始打包它的请求。对于普通的浏览请求,往往会使用**HTTP**协议;但是对于购物的请求,往往需要进行加密传输,因而会使用**HTTPS**协议。无论是什么协议,里面都会写明“你要买什么和买多少”。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/70/e9/70e8ad0531ada8baac174ce6862fede9.jpg" alt="">
|
||||
|
||||
DNS、HTTP、HTTPS所在的层我们称为**应用层**。经过应用层封装后,浏览器会将应用层的包交给下一层去完成,通过socket编程来实现。下一层是**传输层**。传输层有两种协议,一种是无连接的协议**UDP**,一种是面向连接的协议**TCP**。对于支付来讲,往往使用TCP协议。所谓的面向连接就是,TCP会保证这个包能够到达目的地。如果不能到达,就会重新发送,直至到达。
|
||||
|
||||
TCP协议里面会有两个端口,一个是浏览器监听的端口,一个是电商的服务器监听的端口。操作系统往往通过端口来判断,它得到的包应该给哪个进程。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/64/0c/64fcf0cc5baade70769da2160637d70c.jpg" alt="">
|
||||
|
||||
传输层封装完毕后,浏览器会将包交给操作系统的**网络层**。网络层的协议是IP协议。在IP协议里面会有源IP地址,即浏览器所在机器的IP地址和目标IP地址,也即电商网站所在服务器的IP地址。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/19/62/191947411849da8738dfea8394780962.jpg" alt="">
|
||||
|
||||
操作系统既然知道了目标IP地址,就开始想如何根据这个门牌号找到目标机器。操作系统往往会判断,这个目标IP地址是本地人,还是外地人。如果是本地人,从门牌号就能看出来,但是显然电商网站不在本地,而在遥远的地方。
|
||||
|
||||
操作系统知道要离开本地去远方。虽然不知道远方在何处,但是可以这样类比一下:如果去国外要去海关,去外地就要去**网关**。而操作系统启动的时候,就会被DHCP协议配置IP地址,以及默认的网关的IP地址192.168.1.1。
|
||||
|
||||
操作系统如何将IP地址发给网关呢?在本地通信基本靠吼,于是操作系统大吼一声,谁是192.168.1.1啊?网关会回答它,我就是,我的本地地址在村东头。这个本地地址就是**MAC**地址,而大吼的那一声是**ARP**协议。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/9b/79/9b0d10b384ecd0de11c8596f8890df79.jpg" alt="">
|
||||
|
||||
于是操作系统将IP包交给了下一层,也就是**MAC层**。网卡再将包发出去。由于这个包里面是有MAC地址的,因而它能够到达网关。
|
||||
|
||||
网关收到包之后,会根据自己的知识,判断下一步应该怎么走。网关往往是一个路由器,到某个IP地址应该怎么走,这个叫作路由表。
|
||||
|
||||
路由器有点像玄奘西行路过的一个个国家的一个个城关。每个城关都连着两个国家,每个国家相当于一个局域网,在每个国家内部,都可以使用本地的地址MAC进行通信。
|
||||
|
||||
一旦跨越城关,就需要拿出IP头来,里面写着贫僧来自东土大唐(就是源IP地址),欲往西天拜佛求经(指的是目标IP地址)。路过宝地,借宿一晚,明日启程,请问接下来该怎么走啊?
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/08/6f/080495a63148905877f252d097be786f.jpg" alt="">
|
||||
|
||||
城关往往是知道这些“知识”的,因为城关和临近的城关也会经常沟通。到哪里应该怎么走,这种沟通的协议称为**路由协议**,常用的有**OSPF**和**BGP**。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/7a/39/7a59ab81ffe91bbe98cc0b55eba25d39.jpg" alt="">
|
||||
|
||||
城关与城关之间是一个国家,当网络包知道了下一步去哪个城关,还是要使用国家内部的MAC地址,通过下一个城关的MAC地址,找到下一个城关,然后再问下一步的路怎么走,一直到走出最后一个城关。
|
||||
|
||||
最后一个城关知道这个网络包要去的地方。于是,对着这个国家吼一声,谁是目标IP啊?目标服务器就会回复一个MAC地址。网络包过关后,通过这个MAC地址就能找到目标服务器。
|
||||
|
||||
目标服务器发现MAC地址对上了,取下MAC头来,发送给操作系统的网络层。发现IP也对上了,就取下IP头。IP头里会写上一层封装的是TCP协议,然后将其交给传输层,即**TCP层**。
|
||||
|
||||
在这一层里,对于收到的每个包,都会有一个回复的包说明收到了。这个回复的包绝非这次下单请求的结果,例如购物是否成功,扣了多少钱等,而仅仅是TCP层的一个说明,即收到之后的回复。当然这个回复,会沿着刚才来的方向走回去,报个平安。
|
||||
|
||||
因为一旦出了国门,西行路上千难万险,如果在这个过程中,网络包走丢了,例如进了大沙漠,或者被强盗抢劫杀害怎么办呢?因而到了要报个平安。
|
||||
|
||||
如果过一段时间还是没到,发送端的TCP层会重新发送这个包,还是上面的过程,直到有一天收到平安到达的回复。**这个重试绝非你的浏览器重新将下单这个动作重新请求一次**。对于浏览器来讲,就发送了一次下单请求,TCP层不断自己闷头重试。除非TCP这一层出了问题,例如连接断了,才轮到浏览器的应用层重新发送下单请求。
|
||||
|
||||
当网络包平安到达TCP层之后,TCP头中有目标端口号,通过这个端口号,可以找到电商网站的进程正在监听这个端口号,假设一个Tomcat,将这个包发给电商网站。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a3/9e/a35e16acd0912ae3e79567ca0358df9e.jpg" alt="">
|
||||
|
||||
电商网站的进程得到HTTP请求的内容,知道了要买东西,买多少。往往一个电商网站最初接待请求的这个Tomcat只是个接待员,负责统筹处理这个请求,而不是所有的事情都自己做。例如,这个接待员要告诉专门管理订单的进程,登记要买某个商品,买多少,要告诉管理库存的进程,库存要减少多少,要告诉支付的进程,应该付多少钱,等等。
|
||||
|
||||
如何告诉相关的进程呢?往往通过RPC调用,即远程过程调用的方式来实现。远程过程调用就是当告诉管理订单进程的时候,接待员不用关心中间的网络互连问题,会由RPC框架统一处理。RPC框架有很多种,有基于HTTP协议放在HTTP的报文里面的,有直接封装在TCP报文里面的。
|
||||
|
||||
当接待员发现相应的部门都处理完毕,就回复一个HTTPS的包,告知下单成功。这个HTTPS的包,会像来的时候一样,经过千难万险到达你的个人电脑,最终进入浏览器,显示支付成功。
|
||||
|
||||
## 小结
|
||||
|
||||
看到了吧,一个简简单单的下单过程,中间牵扯到这么多的协议。而管理一大片机器,更是一件特别有技术含量的事情。除此之外,像最近比较火的云计算、容器、微服务等技术,也都需要借助各种协议,来达成大规模机器之间的合作。
|
||||
|
||||
我在这里列一下之后要讲的网络协议,之后我会按照从底层到上层的顺序来讲述。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/59/54/5985d6d430e1b1d3f165bf0f916ed954.jpg" alt="">
|
||||
|
||||
上面的“双十一”故事只是为了给你一个大致的框架,这里面有些协议,我在故事里已经提到了,有些还没有提到。在这门课的最后一章,当所有的协议都讲过之后,我会再重新讲一遍这个故事,到时候你就能明白更多的细节。
|
||||
|
||||
最后,学完了这一节,给你留一个问题吧。
|
||||
|
||||
当网络包到达一个城关的时候,可以通过路由表得到下一个城关的IP地址,直接通过IP地址找就可以了,为什么还要通过本地的MAC地址呢?
|
||||
|
||||
欢迎你留言和我讨论。趣谈网络协议,我们下期见!
|
||||
99
极客时间专栏/geek/趣谈网络协议/第一模块 通信协议综述/第2讲 | 网络分层的真实含义是什么?.md
Normal file
99
极客时间专栏/geek/趣谈网络协议/第一模块 通信协议综述/第2讲 | 网络分层的真实含义是什么?.md
Normal file
@@ -0,0 +1,99 @@
|
||||
<audio id="audio" title="第2讲 | 网络分层的真实含义是什么?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/e5/05/e539fc94a00a3db0b72acd53bba93f05.mp3"></audio>
|
||||
|
||||
长时间从事计算机网络相关的工作,我发现,计算机网络有一个显著的特点,就是这是一个不仅需要背诵,而且特别需要将原理烂熟于胸的学科。很多问题看起来懂了,但是就怕往细里问,一问就发现你懂得没有那么透彻。
|
||||
|
||||
我们上一节列了之后要讲的网络协议。这些协议本来没什么稀奇,每一本教科书都会讲,并且都要求你背下来。因为考试会考,面试会问。可以这么说,毕业了去找工作还答不出这类题目的,那你的笔试基本上也就挂了。
|
||||
|
||||
当你听到什么二层设备、三层设备、四层LB和七层LB中层的时候,是否有点一头雾水,不知道这些所谓的层,对应的各种协议具体要做什么“工作”?
|
||||
|
||||
## 这四个问题你真的懂了吗?
|
||||
|
||||
因为教科书或者老师往往会打一个十分不恰当的比喻:为什么网络要分层呀?因为不同的层次之间有不同的沟通方式,这个叫作协议。例如,一家公司也是分“层次”的,分总经理、经理、组长、员工。总经理之间有他们的沟通方式,经理和经理之间也有沟通方式,同理组长和员工。有没有听过类似的比喻?
|
||||
|
||||
那么**第一个问题**来了。请问经理在握手的时候,员工在干什么?很多人听过TCP建立连接的**三次握手协议**,也会把它当知识点背诵。同理问你,TCP在进行三次握手的时候,IP层和MAC层对应都有什么操作呢?
|
||||
|
||||
除了上面这个不恰当的比喻,教科书还会列出每个层次所包含的协议,然后开始逐层地去讲这些协议。但是这些协议之间的关系呢?却很少有教科书会讲。
|
||||
|
||||
学习第三层的时候会提到,IP协议里面包含**目标地址**和**源地址。<strong>第三层里往往还会学习**路由协议</strong>。路由就像中转站,我们从原始地址A到目标地址D,中间经过两个中转站A->B->C->D,是通过路由转发的。
|
||||
|
||||
那么**第二个问题**来了。A知道自己的下一个中转站是B,那从A发出来的包,应该把B的IP地址放在哪里呢?B知道自己的下一个中转站是C,从B发出来的包,应该把C的IP地址放在哪里呢?如果放在IP协议中的目标地址,那包到了中转站,怎么知道最终的目的地址是D呢?
|
||||
|
||||
教科书不会通过场景化的例子,将网络包的生命周期讲出来,所以你就会很困惑,不知道这些协议实际的应用场景是什么。
|
||||
|
||||
我**再问你一个问题**。你一定经常听说二层设备、三层设备。二层设备处理的通常是MAC层的东西。那我发送一个HTTP的包,是在第七层工作的,那是不是不需要经过二层设备?或者即便经过了,二层设备也不处理呢?或者换一种问法,二层设备处理的包里,有没有HTTP层的内容呢?
|
||||
|
||||
最终,我想问你**一个综合的问题**。从你的电脑,通过SSH登录到公有云主机里面,都需要经历哪些过程?或者说你打开一个电商网站,都需要经历哪些过程?说得越详细越好。
|
||||
|
||||
实际情况可能是,很多人回答不上来。尽管对每一层都很熟悉,但是知识点却串不起来。
|
||||
|
||||
上面的这些问题,有的在这一节就会有一个解释,有的则会贯穿我们整个课程。好在后面一节中我会举一个贯穿的例子,将很多层的细节讲过后,你很容易就能把这些知识点串起来。
|
||||
|
||||
## 网络为什么要分层?
|
||||
|
||||
这里我们先探讨第一个问题,网络为什么要分层?因为,是个复杂的程序都要分层。
|
||||
|
||||
理解计算机网络中的概念,一个很好的角度是,想象网络包就是一段Buffer,或者一块内存,是有格式的。同时,想象自己是一个处理网络包的程序,而且这个程序可以跑在电脑上,可以跑在服务器上,可以跑在交换机上,也可以跑在路由器上。你想象自己有很多的网口,从某个口拿进一个网络包来,用自己的程序处理一下,再从另一个网口发送出去。
|
||||
|
||||
当然网络包的格式很复杂,这个程序也很复杂。**复杂的程序都要分层,这是程序设计的要求。**比如,复杂的电商还会分数据库层、缓存层、Compose层、Controller层和接入层,每一层专注做本层的事情。
|
||||
|
||||
## 程序是如何工作的?
|
||||
|
||||
我们可以简单地想象“你”这个程序的工作过程。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/5c/76/5c00f6e610f533d17fb4ad7decacc776.jpg" alt="" />
|
||||
|
||||
当一个网络包从一个网口经过的时候,你看到了,首先先看看要不要请进来,处理一把。有的网口配置了混杂模式,凡是经过的,全部拿进来。
|
||||
|
||||
拿进来以后,就要交给一段程序来处理。于是,你调用**process_layer2(buffer)**。当然,这是一个假的函数。但是你明白其中的意思,知道肯定是有这么个函数的。那这个函数是干什么的呢?从Buffer中,摘掉二层的头,看一看,应该根据头里面的内容做什么操作。
|
||||
|
||||
假设你发现这个包的MAC地址和你的相符,那说明就是发给你的,于是需要调用**process_layer3(buffer)**。这个时候,Buffer里面往往就没有二层的头了,因为已经在上一个函数的处理过程中拿掉了,或者将开始的偏移量移动了一下。在这个函数里面,摘掉三层的头,看看到底是发送给自己的,还是希望自己转发出去的。
|
||||
|
||||
如何判断呢?如果IP地址不是自己的,那就应该转发出去;如果IP地址是自己的,那就是发给自己的。根据IP头里面的标示,拿掉三层的头,进行下一层的处理,到底是调用process_tcp(buffer)呢,还是调用process_udp(buffer)呢?
|
||||
|
||||
假设这个地址是TCP的,则会调用**process_tcp(buffer)**。这时候,Buffer里面没有三层的头,就需要查看四层的头,看这是一个发起,还是一个应答,又或者是一个正常的数据包,然后分别由不同的逻辑进行处理。如果是发起或者应答,接下来可能要发送一个回复包;如果是一个正常的数据包,就需要交给上层了。交给谁呢?是不是有process_http(buffer)函数呢?
|
||||
|
||||
没有的,如果你是一个网络包处理程序,你不需要有process_http(buffer),而是应该交给应用去处理。交给哪个应用呢?在四层的头里面有端口号,不同的应用监听不同的端口号。如果发现浏览器应用在监听这个端口,那你发给浏览器就行了。至于浏览器怎么处理,和你没有关系。
|
||||
|
||||
浏览器自然是解析HTML,显示出页面来。电脑的主人看到页面很开心,就点了鼠标。点击鼠标的动作被浏览器捕获。浏览器知道,又要发起另一个HTTP请求了,于是使用端口号,将请求发给了你。
|
||||
|
||||
你应该调用**send_tcp(buffer)**。不用说,Buffer里面就是HTTP请求的内容。这个函数里面加一个TCP的头,记录下源端口号。浏览器会给你目的端口号,一般为80端口。
|
||||
|
||||
然后调用**send_layer3(buffer)**。Buffer里面已经有了HTTP的头和内容,以及TCP的头。在这个函数里面加一个IP的头,记录下源IP的地址和目标IP的地址。
|
||||
|
||||
然后调用**send_layer2(buffer)**。Buffer里面已经有了HTTP的头和内容、TCP的头,以及IP的头。这个函数里面要加一下MAC的头,记录下源MAC地址,得到的就是本机器的MAC地址和目标的MAC地址。不过,这个还要看当前知道不知道,知道就直接加上;不知道的话,就要通过一定的协议处理过程,找到MAC地址。反正要填一个,不能空着。
|
||||
|
||||
万事俱备,只要Buffer里面的内容完整,就可以从网口发出去了,你作为一个程序的任务就算告一段落了。
|
||||
|
||||
## 揭秘层与层之间的关系
|
||||
|
||||
知道了这个过程之后,我们再来看一下原来困惑的问题。
|
||||
|
||||
首先是分层的比喻。**所有不能表示出层层封装含义的比喻,都是不恰当的。**总经理握手,不需要员工在吧,总经理之间谈什么,不需要员工参与吧,但是网络世界不是这样的。正确的应该是,总经理之间沟通的时候,经理将总经理放在自己兜里,然后组长把经理放自己兜里,员工把组长放自己兜里,像套娃娃一样。那员工直接沟通,不带上总经理,就不恰当了。
|
||||
|
||||
现实生活中,往往是员工说一句,组长补充两句,然后经理补充两句,最后总经理再补充两句。但是在网络世界,应该是总经理说话,经理补充两句,组长补充两句,员工再补充两句。
|
||||
|
||||
那TCP在三次握手的时候,IP层和MAC层在做什么呢?当然是TCP发送每一个消息,都会带着IP层和MAC层了。因为,TCP每发送一个消息,IP层和MAC层的所有机制都要运行一遍。而你只看到TCP三次握手了,其实,IP层和MAC层为此也忙活好久了。
|
||||
|
||||
这里要记住一点:**只要是在网络上跑的包,都是完整的。可以有下层没上层,绝对不可能有上层没下层。**
|
||||
|
||||
所以,**对TCP协议来说,三次握手也好,重试也好,只要想发出去包,就要有IP层和MAC层,不然是发不出去的。**
|
||||
|
||||
经常有人会问这样一个问题,我都知道那台机器的IP地址了,直接发给他消息呗,要MAC地址干啥?这里的关键就是,没有MAC地址消息是发不出去的。
|
||||
|
||||
所以如果一个HTTP协议的包跑在网络上,它一定是完整的。无论这个包经过哪些设备,它都是完整的。
|
||||
|
||||
所谓的二层设备、三层设备,都是这些设备上跑的程序不同而已。一个HTTP协议的包经过一个二层设备,二层设备收进去的是整个网络包。这里面HTTP、TCP、 IP、 MAC都有。什么叫二层设备呀,就是只把MAC头摘下来,看看到底是丢弃、转发,还是自己留着。那什么叫三层设备呢?就是把MAC头摘下来之后,再把IP头摘下来,看看到底是丢弃、转发,还是自己留着。
|
||||
|
||||
## 小结
|
||||
|
||||
总结一下今天的内容,理解网络协议的工作模式,有两个小窍门:
|
||||
|
||||
- 始终想象自己是一个处理网络包的程序:如何拿到网络包,如何根据规则进行处理,如何发出去;
|
||||
- 始终牢记一个原则:只要是在网络上跑的包,都是完整的。可以有下层没上层,绝对不可能有上层没下层。
|
||||
|
||||
最后,给你留两个思考题吧。
|
||||
|
||||
1. 如果你也觉得总经理和员工的比喻不恰当,你有更恰当的比喻吗?
|
||||
1. 要想学习网络协议,IP这个概念是最最基本的,那你知道如何查看IP地址吗?
|
||||
|
||||
欢迎你留言和我讨论。趣谈网络协议,我们下期见!
|
||||
149
极客时间专栏/geek/趣谈网络协议/第一模块 通信协议综述/第3讲 | ifconfig:最熟悉又陌生的命令行.md
Normal file
149
极客时间专栏/geek/趣谈网络协议/第一模块 通信协议综述/第3讲 | ifconfig:最熟悉又陌生的命令行.md
Normal file
@@ -0,0 +1,149 @@
|
||||
<audio id="audio" title="第3讲 | ifconfig:最熟悉又陌生的命令行" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/2b/da/2be5885efb35636c8351bf2058aba2da.mp3"></audio>
|
||||
|
||||
上一节结尾给你留的一个思考题是,你知道怎么查看IP地址吗?
|
||||
|
||||
当面试听到这个问题的时候,面试者常常会觉得走错了房间。我面试的是技术岗位啊,怎么问这么简单的问题?
|
||||
|
||||
的确,即便没有专业学过计算机的人,只要倒腾过电脑,重装过系统,大多也会知道这个问题的答案:在Windows上是ipconfig,在Linux上是ifconfig。
|
||||
|
||||
那你知道在Linux上还有什么其他命令可以查看IP地址吗?答案是ip addr。如果回答不上来这个问题,那你可能没怎么用过Linux。
|
||||
|
||||
那你知道ifconfig和ip addr的区别吗?这是一个有关net-tools和iproute2的“历史”故事,你刚来到第三节,暂时不用了解这么细,但这也是一个常考的知识点。
|
||||
|
||||
想象一下,你登录进入一个被裁剪过的非常小的Linux系统中,发现既没有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地址的情况。
|
||||
|
||||
IP地址是一个网卡在网络世界的通讯地址,相当于我们现实世界的门牌号码。既然是门牌号码,不能大家都一样,不然就会起冲突。比方说,假如大家都叫六单元1001号,那快递就找不到地方了。所以,有时候咱们的电脑弹出网络地址冲突,出现上不去网的情况,多半是IP地址冲突了。
|
||||
|
||||
如上输出的结果,10.100.122.2就是一个IP地址。这个地址被点分隔为四个部分,每个部分8个bit,所以IP地址总共是32位。这样产生的IP地址的数量很快就不够用了。因为当时设计IP地址的时候,哪知道今天会有这么多的计算机啊!因为不够用,于是就有了IPv6,也就是上面输出结果里面inet6 fe80::f816:3eff:fec7:7975/64。这个有128位,现在看来是够了,但是未来的事情谁知道呢?
|
||||
|
||||
本来32位的IP地址就不够,还被分成了5类。现在想想,当时分配地址的时候,真是太奢侈了。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/fa/5e/fa9a00346b8a83a84f4c00de948a5b5e.jpg" alt="">
|
||||
|
||||
在网络地址中,至少在当时设计的时候,对于A、B、 C类主要分两部分,前面一部分是网络号,后面一部分是主机号。这很好理解,大家都是六单元1001号,我是小区A的六单元1001号,而你是小区B的六单元1001号。
|
||||
|
||||
下面这个表格,详细地展示了A、B、C三类地址所能包含的主机的数量。在后文中,我也会多次借助这个表格来讲解。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/6d/4c/6de9d39a68520c8e3b75aa919fadb24c.jpg" alt="">
|
||||
|
||||
这里面有个尴尬的事情,就是C类地址能包含的最大主机数量实在太少了,只有254个。当时设计的时候恐怕没想到,现在估计一个网吧都不够用吧。而B类地址能包含的最大主机数量又太多了。6万多台机器放在一个网络下面,一般的企业基本达不到这个规模,闲着的地址就是浪费。
|
||||
|
||||
## 无类型域间选路(CIDR)
|
||||
|
||||
于是有了一个折中的方式叫作**无类型域间选路**,简称**CIDR**。这种方式打破了原来设计的几类地址的做法,将32位的IP地址一分为二,前面是**网络号**,后面是**主机号**。从哪里分呢?你如果注意观察的话可以看到,10.100.122.2/24,这个IP地址中有一个斜杠,斜杠后面有个数字24。这种地址表示形式,就是CIDR。后面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,就可得到网络号。**
|
||||
|
||||
## 公有IP地址和私有IP地址
|
||||
|
||||
在日常的工作中,几乎不用划分A类、B类或者C类,所以时间长了,很多人就忘记了这个分类,而只记得CIDR。但是有一点还是要注意的,就是公有IP地址和私有IP地址。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/df/a9/df90239efec6e35880b9abe55089ffa9.jpg" alt="">
|
||||
|
||||
我们继续看上面的表格。表格最右列是私有IP地址段。平时我们看到的数据中心里,办公室、家里或学校的IP地址,一般都是私有IP地址段。因为这些地址允许组织内部的IT人员自己管理、自己分配,而且可以重复。因此,你学校的某个私有IP地址段和我学校的可以是一样的。
|
||||
|
||||
这就像每个小区有自己的楼编号和门牌号,你们小区可以叫6栋,我们小区也叫6栋,没有任何问题。但是一旦出了小区,就需要使用公有IP地址。就像人民路888号,是国家统一分配的,不能两个小区都叫人民路888号。
|
||||
|
||||
公有IP地址有个组织统一分配,你需要去买。如果你搭建一个网站,给你学校的人使用,让你们学校的IT人员给你一个IP地址就行。但是假如你要做一个类似网易163这样的网站,就需要有公有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网络里面的所有机器都能收到。
|
||||
|
||||
但是也不总都是这样的情况。因此,其他情况往往就会很难理解,还容易出错。
|
||||
|
||||
## 举例:一个容易“犯错”的CIDR
|
||||
|
||||
我们来看16.158.165.91/22这个CIDR。求一下这个网络的第一个地址、子网掩码和广播地址。
|
||||
|
||||
你要是上来就写16.158.165.1,那就大错特错了。
|
||||
|
||||
/22不是8的整数倍,不好办,只能先变成二进制来看。16.158的部分不会动,它占了前16位。中间的165,变为二进制为10100101。除了前面的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这个地址。这个地址用于本机通信,经过内核处理后直接返回,不会在任何网络中出现。
|
||||
|
||||
## MAC地址
|
||||
|
||||
在IP地址的上一行是link/ether fa:16:3e:c7:79:75 brd ff:ff:ff:ff:ff:ff,这个被称为**MAC地址**,是一个网卡的物理地址,用十六进制,6个byte表示。
|
||||
|
||||
MAC地址是一个很容易让人“误解”的地址。因为MAC地址号称全局唯一,不会有两个网卡有相同的MAC地址,而且网卡自生产出来,就带着这个地址。很多人看到这里就会想,既然这样,整个互联网的通信,全部用MAC地址好了,只要知道了对方的MAC地址,就可以把信息传过去。
|
||||
|
||||
这样当然是不行的。 **一个网络包要从一个地方传到另一个地方,除了要有确定的地址,还需要有定位功能。** 而有门牌号码属性的IP地址,才是有远程定位功能的。
|
||||
|
||||
例如,你去杭州市网商路599号B楼6层找刘超,你在路上问路,可能被问的人不知道B楼是哪个,但是可以给你指网商路怎么去。但是如果你问一个人,你知道这个身份证号的人在哪里吗?可想而知,没有人知道。
|
||||
|
||||
MAC地址更像是身份证,是一个唯一的标识。它的唯一性设计是为了组网的时候,不同的网卡放在一个网络里面的时候,可以不用担心冲突。从硬件角度,保证不同的网卡有不同的标识。
|
||||
|
||||
MAC地址是有一定定位功能的,只不过范围非常有限。你可以根据IP地址,找到杭州市网商路599号B楼6层,但是依然找不到我,你就可以靠吼了,大声喊身份证XXXX的是哪位?我听到了,我就会站起来说,是我啊。但是如果你在上海,到处喊身份证XXXX的是哪位,我不在现场,当然不会回答,因为我在杭州不在上海。
|
||||
|
||||
所以,MAC地址的通信范围比较小,局限在一个子网里面。例如,从192.168.0.2/24访问192.168.0.3/24是可以用MAC地址的。一旦跨子网,即从192.168.0.2/24到192.168.1.2/24,MAC地址就不行了,需要IP地址起作用了。
|
||||
|
||||
## 网络设备的状态标识
|
||||
|
||||
解析完了MAC地址,我们再来看 <BROADCAST,MULTICAST,UP,LOWER_UP>是干什么的?这个叫做**net_device flags**,**网络设备的状态标识**。
|
||||
|
||||
UP表示网卡处于启动的状态;BROADCAST表示这个网卡有广播地址,可以发送广播包;MULTICAST表示网卡可以发送多播包;LOWER_UP表示L1是启动的,也即网线插着呢。MTU1500是指什么意思呢?是哪一层的概念呢?最大传输单元MTU为1500,这是以太网的默认值。
|
||||
|
||||
上一节,我们讲过网络包是层层封装的。MTU是二层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头里面的一个字段,代表了当前的包是高优先级的,还是低优先级的。
|
||||
|
||||
队列是个好东西,后面我们讲云计算中的网络的时候,会有很多用户共享一个网络出口的情况,这个时候如何排队,每个队列有多粗,队列处理速度应该怎么提升,我都会详细为你讲解。
|
||||
|
||||
## 小结
|
||||
|
||||
怎么样,看起来很简单的一个命令,里面学问很大吧?通过这一节,希望你能记住以下的知识点,后面都能用得上:
|
||||
|
||||
<li>
|
||||
IP是地址,有定位功能;MAC是身份证,无定位功能;
|
||||
</li>
|
||||
<li>
|
||||
CIDR可以用来判断是不是本地人;
|
||||
</li>
|
||||
<li>
|
||||
IP分公有的IP和私有的IP。后面的章节中我会谈到“出国门”,就与这个有关。
|
||||
</li>
|
||||
|
||||
最后,给你留两个思考题。
|
||||
|
||||
1. 你知道net-tools和iproute2的“历史”故事吗?
|
||||
1. 这一节讲的是如何查看IP地址,那你知道IP地址是怎么来的吗?
|
||||
|
||||
欢迎你留言和我讨论。趣谈网络协议,我们下期见!
|
||||
178
极客时间专栏/geek/趣谈网络协议/第一模块 通信协议综述/第4讲 | DHCP与PXE:IP是怎么来的,又是怎么没的?.md
Normal file
178
极客时间专栏/geek/趣谈网络协议/第一模块 通信协议综述/第4讲 | DHCP与PXE:IP是怎么来的,又是怎么没的?.md
Normal file
@@ -0,0 +1,178 @@
|
||||
<audio id="audio" title="第4讲 | DHCP与PXE:IP是怎么来的,又是怎么没的?" controls="" preload="none"><source id="mp3" src="https://static001.geekbang.org/resource/audio/8f/35/8fcc98e770f39dc43af82f717ffd4f35.mp3"></audio>
|
||||
|
||||
上一节,我们讲了IP的一些基本概念。如果需要和其他机器通讯,我们就需要一个通讯地址,我们需要给网卡配置这么一个地址。
|
||||
|
||||
## 如何配置IP地址?
|
||||
|
||||
那如何配置呢?如果有相关的知识和积累,你可以用命令行自己配置一个地址。可以使用ifconfig,也可以使用ip addr。设置好了以后,用这两个命令,将网卡up一下,就可以开始工作了。
|
||||
|
||||
**使用net-tools:**
|
||||
|
||||
```
|
||||
$ sudo ifconfig eth1 10.0.0.1/24
|
||||
$ sudo ifconfig eth1 up
|
||||
|
||||
```
|
||||
|
||||
**使用iproute2:**
|
||||
|
||||
```
|
||||
$ sudo ip addr add 10.0.0.1/24 dev eth1
|
||||
$ sudo ip link set up eth1
|
||||
|
||||
```
|
||||
|
||||
你可能会问了,自己配置这个自由度太大了吧,我是不是配置什么都可以?如果配置一个和谁都不搭边的地址呢?例如,旁边的机器都是192.168.1.x,我非得配置一个16.158.23.6,会出现什么现象呢?
|
||||
|
||||
不会出现任何现象,就是包发不出去呗。为什么发不出去呢?我来举例说明。
|
||||
|
||||
192.168.1.6就在你这台机器的旁边,甚至是在同一个交换机上,而你把机器的地址设为了16.158.23.6。在这台机器上,你企图去ping192.168.1.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呢?
|
||||
|
||||
所以,当你需要手动配置一台机器的网络IP时,一定要好好问问你的网络管理员。如果在机房里面,要去网络管理员那里申请,让他给你分配一段正确的IP地址。当然,真正配置的时候,一定不是直接用命令配置的,而是放在一个配置文件里面。**不同系统的配置文件格式不同,但是无非就是CIDR、子网掩码、广播地址和网关地址**。
|
||||
|
||||
## 动态主机配置协议(DHCP)
|
||||
|
||||
原来配置IP有这么多门道儿啊。你可能会问了,配置了IP之后一般不能变的,配置一个服务端的机器还可以,但是如果是客户端的机器呢?我抱着一台笔记本电脑在公司里走来走去,或者白天来晚上走,每次使用都要配置IP地址,那可怎么办?还有人事、行政等非技术人员,如果公司所有的电脑都需要IT人员配置,肯定忙不过来啊。
|
||||
|
||||
因此,我们需要有一个自动配置的协议,也就是**动态主机配置协议(Dynamic Host Configuration Protocol)**,简称**DHCP**。
|
||||
|
||||
有了这个协议,网络管理员就轻松多了。他只需要配置一段共享的IP地址。每一台新接入的机器都通过DHCP协议,来这个共享的IP地址里申请,然后自动配置好就可以了。等人走了,或者用完了,还回去,这样其他的机器也能用。
|
||||
|
||||
所以说,**如果是数据中心里面的服务器,IP一旦配置好,基本不会变,这就相当于买房自己装修。DHCP的方式就相当于租房。你不用装修,都是帮你配置好的。你暂时用一下,用完退租就可以了。**
|
||||
|
||||
## 解析DHCP的工作方式
|
||||
|
||||
当一台机器新加入一个网络的时候,肯定一脸懵,啥情况都不知道,只知道自己的MAC地址。怎么办?先吼一句,我来啦,有人吗?这时候的沟通基本靠“吼”。这一步,我们称为**DHCP Discover。**
|
||||
|
||||
新来的机器使用IP地址0.0.0.0发送了一个广播包,目的IP地址为255.255.255.255。广播包封装了UDP,UDP封装了BOOTP。其实DHCP是BOOTP的增强版,但是如果你去抓包的话,很可能看到的名称还是BOOTP协议。
|
||||
|
||||
在这个广播包里面,新人大声喊:我是新来的(Boot request),我的MAC地址是这个,我还没有IP,谁能给租给我个IP地址!
|
||||
|
||||
格式就像这样:
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/90/81/90b4d41ee38e891031705d987d5d8481.jpg" alt="">
|
||||
|
||||
如果一个网络管理员在网络里面配置了**DHCP Server**的话,他就相当于这些IP的管理员。他立刻能知道来了一个“新人”。这个时候,我们可以体会MAC地址唯一的重要性了。当一台机器带着自己的MAC地址加入一个网络的时候,MAC是它唯一的身份,如果连这个都重复了,就没办法配置了。
|
||||
|
||||
只有MAC唯一,IP管理员才能知道这是一个新人,需要租给它一个IP地址,这个过程我们称为**DHCP Offer**。同时,DHCP Server为此客户保留为它提供的IP地址,从而不会为其他DHCP客户分配此IP地址。
|
||||
|
||||
DHCP Offer的格式就像这样,里面有给新人分配的地址。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/a5/6b/a52c8c87b925b52059febe9dfcd6be6b.jpg" alt="">
|
||||
|
||||
DHCP Server仍然使用广播地址作为目的地址,因为,此时请求分配IP的新人还没有自己的IP。DHCP Server回复说,我分配了一个可用的IP给你,你看如何?除此之外,服务器还发送了子网掩码、网关和IP地址租用期等信息。
|
||||
|
||||
新来的机器很开心,它的“吼”得到了回复,并且有人愿意租给它一个IP地址了,这意味着它可以在网络上立足了。当然更令人开心的是,如果有多个DHCP Server,这台新机器会收到多个IP地址,简直受宠若惊。
|
||||
|
||||
它会选择其中一个DHCP Offer,一般是最先到达的那个,并且会向网络发送一个DHCP Request广播数据包,包中包含客户端的MAC地址、接受的租约中的IP地址、提供此租约的DHCP服务器地址等,并告诉所有DHCP Server它将接受哪一台服务器提供的IP地址,告诉其他DHCP服务器,谢谢你们的接纳,并请求撤销它们提供的IP地址,以便提供给下一个IP租用请求者。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/cd/fa/cdbcaad24e1a4d24dd724e38f6f043fa.jpg" alt="">
|
||||
|
||||
此时,由于还没有得到DHCP Server的最后确认,客户端仍然使用0.0.0.0为源IP地址、255.255.255.255为目标地址进行广播。在BOOTP里面,接受某个DHCP Server的分配的IP。
|
||||
|
||||
当DHCP Server接收到客户机的DHCP request之后,会广播返回给客户机一个DHCP ACK消息包,表明已经接受客户机的选择,并将这一IP地址的合法租用信息和其他的配置信息都放入该广播包,发给客户机,欢迎它加入网络大家庭。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/cc/a9/cca8b0baa4749bb359e453b1b482e1a9.jpg" alt="">
|
||||
|
||||
最终租约达成的时候,还是需要广播一下,让大家都知道。
|
||||
|
||||
## IP地址的收回和续租
|
||||
|
||||
既然是租房子,就是有租期的。租期到了,管理员就要将IP收回。
|
||||
|
||||
如果不用的话,收回就收回了。就像你租房子一样,如果还要续租的话,不能到了时间再续租,而是要提前一段时间给房东说。DHCP也是这样。
|
||||
|
||||
客户机会在租期过去50%的时候,直接向为其提供IP地址的DHCP Server发送DHCP request消息包。客户机接收到该服务器回应的DHCP ACK消息包,会根据包中所提供的新的租期以及其他已经更新的TCP/IP参数,更新自己的配置。这样,IP租用更新就完成了。
|
||||
|
||||
好了,一切看起来完美。DHCP协议大部分人都知道,但是其实里面隐藏着一个细节,很多人可能不会去注意。接下来,我就讲一个有意思的事情:网络管理员不仅能自动分配IP地址,还能帮你自动安装操作系统!
|
||||
|
||||
## 预启动执行环境(PXE)
|
||||
|
||||
普通的笔记本电脑,一般不会有这种需求。因为你拿到电脑时,就已经有操作系统了,即便你自己重装操作系统,也不是很麻烦的事情。但是,在数据中心里就不一样了。数据中心里面的管理员可能一下子就拿到几百台空的机器,一个个安装操作系统,会累死的。
|
||||
|
||||
所以管理员希望的不仅仅是自动分配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服务器上下载某个文件,去初始化操作系统。
|
||||
|
||||
## 解析PXE的工作过程
|
||||
|
||||
接下来我们来详细看一下PXE的工作过程。
|
||||
|
||||
首先,启动PXE客户端。第一步是通过DHCP协议告诉DHCP Server,我刚来,一穷二白,啥都没有。DHCP Server便租给它一个IP地址,同时也给它PXE服务器的地址、启动文件pxelinux.0。
|
||||
|
||||
其次,PXE客户端知道要去PXE服务器下载这个文件后,就可以初始化机器。于是便开始下载,下载的时候使用的是TFTP协议。所以PXE服务器上,往往还需要有一个TFTP服务器。PXE客户端向TFTP服务器请求下载这个文件,TFTP服务器说好啊,于是就将这个文件传给它。
|
||||
|
||||
然后,PXE客户端收到这个文件后,就开始执行这个文件。这个文件会指示PXE客户端,向TFTP服务器请求计算机的配置信息pxelinux.cfg。TFTP服务器会给PXE客户端一个配置文件,里面会说内核在哪里、initramfs在哪里。PXE客户端会请求这些文件。
|
||||
|
||||
最后,启动Linux内核。一旦启动了操作系统,以后就啥都好办了。
|
||||
|
||||
<img src="https://static001.geekbang.org/resource/image/bb/8e/bbc2b660bba0ad00b5d1179db158498e.jpg" alt="">
|
||||
|
||||
## 小结
|
||||
|
||||
好了,这一节就到这里了。我来总结一下今天的内容:
|
||||
|
||||
<li>
|
||||
DHCP协议主要是用来给客户租用IP地址,和房产中介很像,要商谈、签约、续租,广播还不能“抢单”;
|
||||
</li>
|
||||
<li>
|
||||
DHCP协议能给客户推荐“装修队”PXE,能够安装操作系统,这个在云计算领域大有用处。
|
||||
</li>
|
||||
|
||||
最后,学完了这一节,给你留两个思考题吧。
|
||||
|
||||
1. PXE协议可以用来安装操作系统,但是如果每次重启都安装操作系统,就会很麻烦。你知道如何使得第一次安装操作系统,后面就正常启动吗?
|
||||
1. 现在上网很简单了,买个家用路由器,连上WIFI,给DHCP分配一个IP地址,就可以上网了。那你是否用过更原始的方法自己组过简单的网呢?说来听听。
|
||||
|
||||
欢迎你留言和我讨论。趣谈网络协议,我们下期见!
|
||||
Reference in New Issue
Block a user