1.网络层
网络层最主要的协议就是IP协议。
下图是IP协议的格式:
1.1 IP协议解析
(1)4位版本:
有两种:IPV4(IP地址4个字节大小)和IPV6(IP地址16个字节大小)
(2)4位首部长度:
IP协议的报头长度同TCP类似的,是变长的,范围:0~0xF(单位为4字节)
(3)8位服务类型:
能够让IP协议切换形态。包括:3位优先权字段(已经弃用),4位TOS字段(这4位字段是冲突的,也就是说只能有一位是1,不同位设1表示IP协议不同的状态,分别表示:最小延时,最小吞吐量,最小成本,最高可靠性),1位保留字段
(4)16位总长度:
描述IP协议包的最大长度,范围:0~65535,不超过64KB(但IP协议自身支持拆包组包功能)。
(5)16位标识:
如果一个大的IP协议数据包被拆分成一个一个小的包,每一个小包中的标识位就相同。
(6)3位标识:
有一位表示是否允许拆包,还有一位表示是否是最后一个包。
(7)13位偏移:
表示每一个小的数据包的相对位置。
(8)8位生存时间(TTL):
描述了一个IP数据包在网络上能够存活的时间。IP数据包在被构造出来时,TTL(次数)都会设置一个初始值,数据包在转发过程中,每经过一个路由器就会使TTL减少一次,直至TTL为0,如果TTL已经为0,但是还没有到达目的地,就会被丢弃掉。
(9)8位协议:
描述的是IP数据包的载荷部分,是TCP/UDP数据包。
(10)16位首部校验和:
只是校验IP的头部,不会校验载荷。(原理与UDP校验和相同)
(11)源IP地址/目的IP地址:
IP协议中最重要的一部分,4个字节大小,采用点分十进制的方式来进行表示。
1.2 网络层的主要作用
(1)地址管理:
指定一系列规则,通过地址,描述出一个设备在网络上的位置。
IP地址是一个32位的整数(42亿9千万),互联网发展到前天,能够上网的设备早就超过了IP地址所能表示的最大范围,很明显IP地址已经不够用了。
那么如何解决IP地址不够用的问题呢?
方案一:动态分配IP地址=>治标不治本,提高了IP地址的利用率,并没有增加IP地址的数量。
eg:美国与我们国家有时差,我们这里一般是白天,他们那边就是晚上,同样我们这边是晚上,他们那边是白天,晚上都都睡觉就不会分配IP地址,白天才会分配IP地址。
方案二:NAT转换机制
IP地址分为两类:
1)外网IP(外域网IP);除了内网IP之外的所有IP。
2)内网IP(局域网IP):如果一个IP是192.168.*或10.*或172.16.*~172.31.*,则为内网IP。
当前情况下,一个小区/学校/公司统一使用一个局域网,局域网中可能有成千上万个IP,然后这个局域网有一个外网IP,局域网内部的设备要想访问外网都会经过NAT将IP地址转换成外网IP,从而就可以访问了。
NAT具体工作:
如果是只有一台机器,那么只需要源IP和目的IP就足够了,IP数据包在经过NAT的时候,NAT会将IP数据包报头中的源IP(原来是一个内网IP),给替换成局域网的外网IP(内网IP不允许在外网中使用),并且建立映射关系(原来的内网IP与局域网的外网IP,以便响应返回的时候,能够映射回去)。
如果是多台机器,仅仅只有IP地址就不行了,还需要结合端口号来进行访问:
1)源IP不同,端口号也不同:
多个数据包在经过NAT的时候,NAT会将每一个IP数据包报头中的源IP(原来是一个内网IP),给替换成局域网的外网IP,端口号还是原来的,并且建立映射关系(源IP+端口号 和 局域网IP+端口号),然后就可以进行访问了。
2)源IP不同,端口号相同:
多个数据包在经过NAT的时候,NAT会将每一个IP数据包报头中的源IP(原来是一个内网IP),给替换成局域网的外网IP,端口号也需要进行转换(NAT会自动分配两个不一样的端口号),并且建立映射关系(有两个:源IP和局域网IP,源端口号和经NAT转换后的端口号),然后就可以进行访问了。
当前就是采用动态分配IP地址和NAT转换机制来解决IP地址不够用的问题。
方案三:使用IPv6:16个字节,可以来说是相当大了(可以给地球上的每一粒沙子都给分配一个IP地址)。
但是IPv6最大的问题在于和IPv4不兼容,要想支持IPv6就得升级设备,我们国家是IPv6普及程度最高的国家(没有之一),这是国家大力推进的结果。IPv6一般要使用得手动开启。
(2)路由选择:
描述IP协议的转发过程,网络环境是复杂的,从一个节点到另一个节点之间,存在很多条不同的路径,就需要通过这种方式,筛选出更合适的路径进行数据传输。
IP数据包在转发的时候,每一个路由器是无法像地图那样知晓网络的全貌,只知道一些局部信息,也就是一个路由器不知道它自己与哪些路由器相连。这也就意味着IP数据包在转发过程中是一个“探索式”的过程。
具体过程:
数据包每到一个路由器,就会通过其中的一个数据结构-“路由表”进行查询下一步向哪转发,最终到达目的地。如果查找到了就按照查找到的进行转发,否则就按照默认的地址进行转发。
1.3 IP地址的其他知识点
IP地址由网络号(标识了一个局域网)和主机号(标识了一个局域网中的设备)组成。一个局域网中的主机号不允许相同,不同局域网之间网络号肯定也是不相同的。
一个IP地址哪个是网络号,哪个是主机号是由子网掩码决定的。
子网掩码:也是一位32位整数,左侧都为1,右侧都为0,不会出现0,1交替的情况。
子网掩码为1的数量就是网络号的数量,为0的数量就是主机号的数量。
如果一个IP地址主机号全为0,就代表这个IP地址是一个局域网,不能用来表示任何主机设备。
如果一个IP地址主机号全为1,就代表这个IP地址是一个广播地址。(UDP天然支持广播)
2.数据链路层
主要常见的协议是以太网协议。
下图是以太网协议的格式:
2.1 以太网数据包解析
(1)目的地址/源地址(mac地址):
6个字节,比IPv4大很多,目前来说每一个设备都有一个mac地址(可以作为一台网络设备的身份标识,一般来说网卡一经出场就被写死了,不能进行修改)。
IP地址和mac地址有什么区别呢?
IP地址和mac地址用于不同的地方。IP地址更关注全局,完成整个通信过程中的路径规划工作。
mac地址更关注于局部,相邻两个节点之间是如何进行转发的。
eg:就好比我现在要去北京,中间可能会途经很多城市,现在有计划的的路径是:绵阳-成都-西安-北京,网络中类似于这个过程就是IP做的,而每到一个城市具体座什么车就是mac所需要考虑的。
并且每到一个城市源目的地和目的地就会发生变化,也就类似于每到一个节点,源mac和目的mac地址就会变换。
(2)2位类型:
描述当前数据包是一个什么类型。
(3)IP数据报,ARP请求/应答,RARP请求/应答:
1)IP数据报:
存储业务数据的数据报,最大长度是1500字节,主要取决于MTU(数据链路层数据报所能承载的最大数据长度),不同的数据链路层的MTU不同(和物理介质有关)。
2)ARP/RARP请求/应答:
不存储任何业务数据,只是进行辅助转发的协议。
以太网数据报具体转发过程:
也是类似于IP数据报转发的过程,在交换机内部有一个类似于“路由表”的一个数据结构-“转发表”(就是用ARP协议实现的)。
3.应用层
3.1 DNS(域名解析系统)
使用IP地址,来描述一个设备在网络上的位置。
eg:www.baidu.com,www.sogou.com....这些就是域名,由于IP地址难以进行宣传(并且不容易理解),所以引入域名来解决上述问题。
通过DNS把域名翻译成一个IP地址(把域名和IP地址想像成是一对键值对)。
最早的DNS,是通过一个hosts文件来存储域名和IP地址的映射的关系,但是这种方式很麻烦,于是就有一些大佬,搭建了一组DNS服务器,把这样的映射关系存储在服务器中。如果想要访问某个域名,就会先要请求这个服务器,然后服务器响应返回当前域名对应的IP,然后就可以访问目标网站。后续如果有域名的更新,只需要更新这个服务器中的内容即可,不用修改每个用户电脑中的hosts文件。
但全世界每时每刻都会有很多设备要进行DNS的请求,那么这一组服务器能接受这么高的请求量吗?
很明显是不能的,一个服务器能接受的请求量有限,也就是一个服务器的硬盘资源是有限的,服务器处理每个请求都是要消耗一定的资源的,单位时间内,申请的请求越多,消耗的资源越多,当消耗的资源超过了服务器的上限,机器就挂了。
为解决上述问题,就需要做到“高并发”,核心思路就两条:
(1)开源:
搭建DNS的程序员就号召各大网络运营商自行搭建一组“DNS镜像源服务器”,镜像服务器的数据由他们这边来进行负责上传,此时用户访问域名就是访问离自己最近的DNS镜像服务器。
(2)节流:
假如现在一台设备要对某个域名进行10次访问,第一次访问时候,还是会访问就近的镜像服务器,然后通过响应返回的IP访问对应的网站,同时浏览器会存储一下当前访问的结果,在后续访问相同域名时,就直接使用第一次访问的结果即可。
3.2 HTTP
HTTP是一个文本格式的协议,所以在网络传输过程中经常会被压缩,压缩之后体积变小,这样在传输的时候就可以节省网络带宽(网络带宽是硬件最珍贵的资源)。
而UDP/TCP/IP是二进制格式的协议,不需要进行压缩。
3.2.1 URL
计算机中一个比较重要的概念,在很多地方都会设计到。
格式:
解析:
(1)登录信息(认证):现在几乎不会使用了。
(2)服务器地址:可以是IP地址也可以是域名。
(3)服务器端口号:判断当前是哪个应用程序。
对HTTP请求来说默认访问的是80端口;对HTTPS请求来说默认访问443端口。
(4)资源路径:描述了你要访问服务器的哪个资源。
(5)查询字符串:是一种键值对结构的数据,以?开头,用&来分割不同的键值对,键和值之间使用 = 分割。一个URL的query string中的键值对可以有很多个。对于一些特殊的字符:+,/,?,:已经在URL中有特殊用途的字符,此时需要在进行query string的书写时就需要进行转码(ASCII),用%表示转义。(如果出现中文字符,也需要进行转码)
(6)片段标识符:有的网页内容比较长就可以分成多个“分段”,通过分段标识符就可以完成页面内部的跳转。
3.2.2 HTTP的请求
(1)请求方法:
![](https://i-blog.csdnimg.cn/direct/758494a880bb4623a0d9be6561d268da.png)
主要常用的也就是GET,POST和PUT。
关于GET和POST:
对于HTTP请求方法的初心就是为了表示不同的“语义”,但是在实际使用过程中,初心已经被遗忘了,实际上程序员如何使用,凭借自己的心意,所以目前来说GET和POST请求没有任何区别,要说有区别也只是使用习惯上造成的差异:
1)GET请求通常将传递的数据放在query string中,而POST请求通常将要传递的数据放在body中。(当然GET请求也不是不可以将数据放在body中,只是使用习惯上的差异)
2)GET请求通常用来获取资源,而POST请求通常用来提交资源(比如:登录,上传文件)
说法误区:
1)GET请求传递的数据量有限,POST传递的数据量时无限的。
这是一个历史遗留问题,早期的计算机硬件资源匮乏,所以针对URL的query string的长度做出了限制,但现在的计算机的硬件资源已经很富有了,所以query string中能存放的数据量可以很大,甚至也可以使用它上传一些照片/文件。
2)GET请求传递数据是不安全的,POST请求传递数据是安全的。
这个问题也就是来忽悠一下小白,安不安全这个问题在于请求能不能被获取到/是否进行加密。
请求被获取到对于现在来说很简单,随便使用一个抓包工具都可以获取到,也就是也可以拿到query string和body中的内容。所以安全不安全的关键就在于是否进行了加密,而HTTP是明文传输,后续会介绍到HTTPS,它是密文传输。
3)GET请求只能传输文本数据,POST请求能传输文本数据和二进制数据。
GET请求也可以将二进制数据放在body中进行传输。
(2)报头(header):
1)Host:服务器的地址,使用代理的话有可能不同。
2)Content-length:body的数据长度
3)Content-type:body的数据格式
content-length和content-type属性得要有body才会有。后续处理请求的时候,不同的数据格式服务器处理的逻辑不同,同样返回给浏览器数据的时候,也可能设置一下数据格式,不同的数据格式浏览器也有不同的处理方式。
有哪些格式:
请求:
json,form表单,form-data
上传文件的时候会用到后面两种请求中body的数据格式。
响应:
html,css,js,json,图片。
4)User-Agent:
可以用来查看一台什么样的设备在哪进行上网(哪个浏览器)。现在主要用来区分是PC端还是移动端(一个页面在PC端/移动端可能显示的不一样,所以可以用该属性来进行区分一样,什么样的用户端返回对应的页面)。
5)Referer:
描述了当前页面是从哪跳转过来的。Referer的存在可能就用来计算钱的。
eg:搜狗的广告搜索,按照单击计费,用户如果点击了,意味着可能对这块内容感兴趣,进一步就可能促进消费,按照点击计费,也就是单位时间内点击广告多少次=>搜狗和广告主都需要进行统计,此时搜狗就需要通过referer来判断当前页面是不是通过搜狗页面跳转而来,广告主不可能只在一家公司投广告,可能还会在其他地方投广告,所以也需要通过referer来区别不同页面跳转而来,
6)Cookie:
可以认为是浏览器存储数据的一种机制。
浏览器的数据来源于服务器,服务器这边管理了一些核心的1数据,但是程序运行过程中,也会有一些数据,需在浏览器中存储的,后续也可能需要将这些数据发送给服务器(比如上次登录时间,上次访问信息,用户的身份信息,临时性的数据存储在浏览器中比较合适)。
更容易想到的时候,把这些数据存储在本地文件中,但是实际上是不可行的,浏览器为了安全性禁止网页直接访问电脑的本地文件。为了提高安全性就引入了Cookie(也是按照文件的方式保存,但是浏览器把操作文件给封装了,网页只能通过往cookie中存储键值对),后续服务器在发送请求的时候,就会把cookie中的内容给自动带入请求中,传递给服务器,服务器通过cookie中的内容来做逻辑上的一些处理。
3.2.3 HTTP的响应
响应状态码(点击跳转查看具体的状态码):