This commit is contained in:
louzefeng
2024-07-09 18:38:56 +00:00
parent 8bafaef34d
commit bf99793fd0
6071 changed files with 1017944 additions and 0 deletions

View 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(&quot;Hello World!&quot;);
}
}
```
如果你是程序员,一定看得懂上面这一段文字。这是每一个程序员向计算机世界说“你好,世界”的方式。但是,你不一定知道,这段文字也是一种协议,是人类和计算机沟通的协议,**只有通过这种协议,计算机才知道我们想让它做什么。**
## 协议三要素
当然这种协议还是更接近人类语言机器不能直接读懂需要进行翻译翻译的工作教给编译器也就是程序员常说的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
&lt;!DOCTYPE html&gt;
&lt;html&gt;
&lt;head&gt;
&lt;base href=&quot;https://pages.kaola.com/&quot; /&gt;
&lt;meta charset=&quot;utf-8&quot;/&gt; &lt;title&gt;网易考拉3周年主会场&lt;/title&gt;
```
这符合协议的三要素吗?我带你来看一下。
首先,符合语法,也就是说,只有按照上面那个格式来,浏览器才认。例如,上来是**状态**,然后是**首部**,然后是**内容**。
第二符合语义就是要按照约定的意思来。例如状态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地址呢
欢迎你留言和我讨论。趣谈网络协议,我们下期见!

View 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-&gt;B-&gt;C-&gt;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地址吗
欢迎你留言和我讨论。趣谈网络协议,我们下期见!

View 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: &lt;LOOPBACK,UP,LOWER_UP&gt; 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: &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt; 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转换成二进制是00和任何数值取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-FiWi-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.&lt;101001&gt;,而&lt;01&gt;.91是机器号。
第一个地址是16.158.&lt;101001&gt;&lt;00&gt;.1即16.158.164.1。子网掩码是255.255.&lt;111111&gt;&lt;00&gt;.0即255.255.252.0。广播地址为16.158.&lt;101001&gt;&lt;11&gt;.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/24MAC地址就不行了需要IP地址起作用了。
## 网络设备的状态标识
解析完了MAC地址我们再来看 &lt;BROADCAST,MULTICAST,UP,LOWER_UP&gt;是干什么的?这个叫做**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 ServiceTOS**被分配到三个波段band里面的。TOS是IP头里面的一个字段代表了当前的包是高优先级的还是低优先级的。
队列是个好东西,后面我们讲云计算中的网络的时候,会有很多用户共享一个网络出口的情况,这个时候如何排队,每个队列有多粗,队列处理速度应该怎么提升,我都会详细为你讲解。
## 小结
怎么样,看起来很简单的一个命令,里面学问很大吧?通过这一节,希望你能记住以下的知识点,后面都能用得上:
<li>
IP是地址有定位功能MAC是身份证无定位功能
</li>
<li>
CIDR可以用来判断是不是本地人
</li>
<li>
IP分公有的IP和私有的IP。后面的章节中我会谈到“出国门”就与这个有关。
</li>
最后,给你留两个思考题。
1. 你知道net-tools和iproute2的“历史”故事吗
1. 这一节讲的是如何查看IP地址那你知道IP地址是怎么来的吗
欢迎你留言和我讨论。趣谈网络协议,我们下期见!

View File

@@ -0,0 +1,178 @@
<audio id="audio" title="第4讲 | DHCP与PXEIP是怎么来的又是怎么没的" 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。广播包封装了UDPUDP封装了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启动起来然后将权力交给GRUBGRUB加载内核、加载作为根文件系统的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 &quot;pxelinux.0&quot;;
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地址就可以上网了。那你是否用过更原始的方法自己组过简单的网呢说来听听。
欢迎你留言和我讨论。趣谈网络协议,我们下期见!