LCODER网络篇:一个完整的网络传输过程

1,503 阅读18分钟

本文目录

image.png 现如今我们每个人应该都有网上购物,或者是浏览网页的经验。当我们在浏览网页的时候,常规的做法就是打开浏览器,输入网址,浏览器就会给你显示想要访问的网页,那么浏览器是如何做到这件事的呢?今天这篇文章就会详细的讲解这个过程。

首先先用一张图来大致描述一下这个过程。

image.png

1. 一个完整的网络传输过程

1.1 URL转成IP

在浏览器中输入www.baidu.com/ 这是一个URL。浏览器只知道这个URL的名字是“www.baidu.com” ,不知道具体地址,于是,它打开地址簿去寻找,这个地址簿就是DNS,在DNS中查找过后,得到了一串地址:112.80.248.75:443,这个是IP地址,是互联网的门牌号,有了IP地址,就可以找到具体的位置了。

URL叫做统一资源定位符,相当于是网站的名称,IP地址则是网站的具体地址。在互联网中,IP地址就相当于门牌号,比如西湖,西湖的门牌号是:"浙江省杭州市西湖区龙井路1号"。我们一般都只记得网站的名字,而IP地址是一串数字,很难记,也容易弄混。因而需要一个地址簿,这个地址簿就是DNS。在DNS中,一个URL对应一个IP地址,我们通过DNS就可以找到想要的IP地址。

关于DNS是怎么通过URL一步步解析找到IP地址的,后面会详细的讲解,在这里只需要知道,通过DNS我们可以得到想得到的IP地址。

1.2 传输层

传输层就是TCP层,在这一层,会在数据包里添加上一个TCP头,在TCP头里,有两个端口号,分别是源端口号和目标端口号。

知道了目标地址之后,浏览器就开始打包它的请求了,普通的浏览请求,使用HTTP协议,而需要加密的请求,如购物等,需要加密传输,使用HTTPS协议。上面DNS、HTTP、HTTPS所在的层,是应用层。经过应用层的封装之后,浏览器将封装好的包传输到下一层:传输层。

传输层有两种协议,UDP协议和TCP协议。(UDP协议是无连接的,它不能保证上面浏览器传过来的包能到达目的地。TCP则是面向连接的,面向连接的意思就是TCP会保证这个包到达目的地。如果不能到达,就会重新发送,直至到达。)为了保险起见,我们在这一层使用TCP协议进行传输。

TCP协议里有两个端口,一个是浏览器监听的端口,一个是服务器监听的端口。操作系统通过端口来判断,它得到的包应该给哪个进程。

1.3 网络层

网络层也叫IP层,在这一层,会给数据包添加一个IP头,在IP头里,有源IP地址和目标IP地址。

传输层封装完毕后,浏览器将包传递到下一层,也就是网络层,网络层的协议是IP协议。在IP协议里面会有源IP地址,也就是浏览器所在机器的IP地址和目标IP地址。

操作系统知道了目标IP地址,就会想,如何通过这个门牌号找到目标机器,第一步就是要判断,这个IP地址是中国人呢,还是外国人。从112.80.248.75:443这个门牌号就能看出,显然,这个IP地址不是中国人,是外国人。那么操作系统就要出国去寻找,人出国要经过海关,网络包出国就要经过网关。操作系统启动的时候,就会被DHCP协议配置IP地址,以及默认的网关IP192.168.1.1. 操作系统要把这个IP地址交给网关,于是就大吼一声,谁是192.168.1.1啊,网关会回答它:我就是啊,我的地址在村东头。这个地址就是MAC地址,而大吼的那一声就是ARP协议。

1.4 MAC层

在这一层,会给数据包添加上MAC头,MAC头里有目标MAC地址或者是网卡的MAC地址。

接第三条,操作系统得到了网关的MAC地址,就将数据包给了MAC层,在MAC层添加上网关的MAC地址,网卡把包发出去,通过包里面的MAC地址,数据包成功到达网关。

网关收到数据包之后,也要判断下一步怎么走,网关往往是一个路由器,到某个IP地址怎么走,会有一个路由表。路由器就像唐僧取经西行路上的一个个国家和一个个海关,每个海关连着两个国家,每个国家就是一个局域网,每个国家内部通信,都是用本地的地址MAC进行通信.

跨过海关之后,就需要拿出IP头来,里面写着源IP地址和目标IP地址,数据包会拿着这两个地址问海关,接下来该怎么走啊?海关往往是知道要去目标IP地址,下一步该去往那个海关的,因为它们和临近的海关也会经常沟通,这种沟通的协议称为路由协议。路由协议常用的有OSPF和BGP。

当数据包知道了下一步要去向哪个海关之后,在国家内部行走需要MAC地址,通过下一个海关的MAC地址,找到下一个海关,然后再问下一个海关要去向哪里,一直到走出最后一个海关。

最后一个海关知道数据包要去向哪里,于是,对着这个国家大吼一声,谁是目标IP啊?目标服务器就会回复一个MAC地址,数据包过关后,通过这个MAC地址就能找到目标服务器了。

1.5 目标服务器

到了目标服务器,就开始一层一层的把数据包拆卸了,然后对里面的地址。

首先取下MAC头来,发给操作系统的网络层,发现IP对上了,取下IP头。IP头里还有TCP协议,将其交给传输层。

在传输层里,对于收到的每个包,都会有一个回复的包说明收到了,也就是会有个回复沿着刚才来的方向走回去,报个平安。

到达TCP层后,TCP头里有目标端口号,通过这个端口号,可以找到目标网站的进程正在监听这个端口号,此时会有一个tomcat把这个网络包交给目标网站,此时数据包里只剩下HTTP头,目标网站得到HTTP头里的内容,根据HTTP头里的内容,比如,我要搜索那个关键字之类的信息,去展示相应的网页。

tomcat是一个接待员,负责统筹的工作,它会告诉各个进程需要做什么,比如在电商网站买东西,它会告诉管理订单的进程,添加一个订单;告诉管理库存的进程,库存要减少多少;告诉支付的进程,应该付多少钱等。
当tomcat发现所有的处理都处理完成,就回复一个HTTPS的包,这个包会像来的时候一样,经过千难万险回到你的个人电脑,在浏览器显示。

到这里,一个完整的网络传输过程就结束了。

那么接下来,我们就根据这个过程,一个难题一个难题的慢慢研究吧。

2.详解DNS

DNS服务器,就是上面我们所说的地址簿,我想看完上面的过程,你一定十分的好奇,DNS到底是怎么把URL解析成对应的IP地址的?

我们每天在互联网上冲浪的人,数都数不清,而每个人上网基本上都要用到DNS服务器,这对DNS服务器来说是一个很大的挑战,因此DNS服务器必须要设置成高可用,高并发,分布式的,所以就有了这样的树状层次结构。

1673679427(1).png

根DNS服务器:返回顶级域DNS服务器的IP地址
顶级域DNS服务器:返回权威DNS服务器的IP地址
权威DNS服务器:返回相应主机的IP地址

DNS解析流程

看了上面的概念,你一定会很好奇,什么是根DNS服务器,什么是顶级域DNS服务器,又什么是权威DNS服务器啊?
别急,慢慢往下看。

2.1 本地DNS服务器

为了提高DNS的解析性能,很多网络会就近部署DNS缓存服务器,于是当电脑客户端发出一个DNS请求,比如问[www.baidu.com] 的IP是啥啊,首先会发给本地域名服务器(本地DNS),本地DNS一般由你的网络服务商(ISP)如电信,移动等自动分配,它通常在网络服务商的某个机房。 本地DNS收到客户端的请求,在本地DNS服务器上缓存了一张大表,只要它寻找过的IP地址,都会缓存在这张表格上,如果能找到 [www.baidu.com] 的IP地址,它就直接返回。如果没有,它会跑去问它的根域名服务器::“老大,能告诉我[www.baidu.com]的IP地址吗?”

2.2 根DNS服务器

根DNS服务器是最高层次的,全球共13套,它不直接用于域名解析,只指明道路。它接收到本地DNS的请求,发现后缀是.com,说:“噢,这个域名是有.com区域管理的,我给你它的顶级域名服务器的地址,你去问它吧。”

2.3 顶级域名服务器

于是本地DNS拿着这个地址找到.com的顶级域名服务器,问它:“老二,你能告诉我www.baidu.com的IP地址吗?”,顶级域名服务器就是.com、.net、.cn、.org这些一级域名,它负责管理二级域名,如www.baidu.com,它能给本地DNS指明更清晰的方向。顶级域名服务器于是给了本地DNS负责www.baidu.com区域的权威DNS服务器器地址。

2.4 权威DNS服务器

本地DNS问权威DNS服务器:“你好,请问www.baidu.com”的IP地址是啥啊?”,这下子终于问对人了,权威域名服务器就把IP地址给了本地DNS,本地DNS再将IP地址返回给客户端,客户端和目标建立连接。

到这里,就完成了DNS的解析过程,整个过程我画成了一张图。

1673682301(1).png

3. IP地址详解

通过上面的流程,我们知道IP地址相当于网络世界的门牌号码,我们需要通过目的地的IP地址找到目的地。怎么查看IP地址呢?
window中可以通过命令ipconfig来查看,Linux系统中可以通过ifconfig来查看。

image.png

上图中的IPv4地址,就是我们现在用的最多的IP地址:10.10.22.29,这个地址被点分隔为四个部分,每个部分8个bit,所以IP地址总共32位,这样产生的IP地址数量很快就不够用了,于是就有了IPv6,也就是上面输出的fe80::c73d:ec7a:d24a:2e92%11。

3.1 IP地址分类

32位的IP地址被分成了5类。 1673683752(1).png

A、B、C三类IP地址,主要分为两部分,前面一部分是网络号,后面一部分是主机号。

下面这个表格中,详细的展示了A、B、C三类地址所能包含的主机数量。

类别IP地址范围最大主机数私有IP地址范围
A0.0.0.0 - 127.255.255.2551677721410.0.0.0 - 10.255.255.255
B128.0.0.0 - 191.255.255.25565534172.16.0.0 - 172.31.255.255
C192.0.0.0 - 223.255.255.255254192.168.0.0 - 192.168.255.255

C类地址能包含的主机数量太少了,只有254个,因此有了一个折中的方式叫作无类型域间选路,简称CIDR。

3.2 CIDR

CIDR的表现形式是10.100.122.2/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,就可得到网络号。

3.3 公有IP地址和私有IP地址

再来看一下这个表格,表格中最右一列就是私有IP地址范围。

类别IP地址范围最大主机数私有IP地址范围
A0.0.0.0 - 127.255.255.2551677721410.0.0.0 - 10.255.255.255
B128.0.0.0 - 191.255.255.25565534172.16.0.0 - 172.31.255.255
C192.0.0.0 - 223.255.255.255254192.168.0.0 - 192.168.255.255

每个小区都有自己的楼栋号和门牌号,你们小区可以有一个12栋1101,我们小区也可以有。我们可以把私有ip地址想象成楼栋号和门牌号。平时我们看到办公室,家里,学校一般都是私有IP地址,这些地址允许组织内部IT人员自己管理和分配,而且可以重复。但是一旦出了小区,就需要使用公有的IP地址,公有IP地址有个组织统一分配,需要购买。当你搭建一个网站可以让全世界的人访问的时候,就需要购买一个公有IP地址。

表格中的192.168.0.x是最常用的私有IP地址,家里的wifi,对应就会有一个IP地址,一般家里的上网设备不会超过256个,所以/24基本就足够了。192.168.0是网络号,后面是主机号。整个网络里面第一个地址192.168.0.1,往往就是整个私有网络的出口地址,比如说路由器地址。192.168.0.255就是广播地址,一旦发送这个地址,整个192.168.0网络里面的机器都能收到。

3.4 MAC地址

MAC地址,是一个网卡的物理地址,十六进制,用6个byte表示。MAC地址其实相当于网卡的身份证,是全局唯一的,也就是说,这个世界上不会有两个网卡的MAC地址是相同的。它的唯一性设计是为了组网的时候,不同的网卡放在一个网络里面的时候,不用担心冲突。

MAC地址是有一定的定位功能的,但非常有限。我们一般通过地址找人,不会通过身份证找人,所以先要通过IP地址找到范围,再在这个范围里面通过MAC地址找到具体的网卡。所以,MAC地址的通信范围比较小,局限在一个子网里面。

4. 传输层详解

传输层里面有两个协议,UDP协议和TCP协议。TCP是面向连接的,UDP是面向无连接的。具体是个什么意思呢?在互通之前,面向连接的协议会先建立连接,所谓的建立连接是为了在客户端和服务端维护连接,而建立一定的数据结构来维护双方交互的状态,用这样的数据结构来保证所谓的面向连接的特性。所以TCP有三次握手。

但UDP就继承了IP包的特性,不保证不丢失,不保证按顺序到达。

4.1 UDP协议

4.1.1 UDP包头

第一节已经讲过包的传输过程,当我发送的UDP包到达目标机器后,发现MAC地址匹配,于是就取下来,交给IP层,IP层取下IP头,发现目标IP匹配,接下来的数据包给谁,就一步步来分析。

首先,看IP头,IP头里面有个8位协议,这里存放的是数据里面到底是TCP还是UDP。 如果是UDP就根据UDP包头的格式解析数据,UDP包头的格式如下:

image.png

可以看到UDP头里面只有一个源端口号和目标端口号,非常简单。根据目标端口号把数据交给监听相应端口号的程序。

4.1.2 UDP的三大使用场景
  1. 需要资源少,在网络情况比较好的内网,或者对于丢包不敏感的应用。
  2. 不需要一对一沟通,建立连接,而是可以广播的应用。
  3. 需要处理速度快,时延低,可以容忍少数丢包,比如直播的数据。

4.2 TCP协议

TCP协议和UDP协议不一样,TCP协议认为网络环境是恶劣的,丢包、乱序、重传、拥塞都是常有的事,一言不合就可能到达不了,因而需要从算法层面来保证可靠性。

4.2.1 TCP包头格式

首先我们来看一下TCP头的格式。

image.png

源端口号和目标端口号,和UDP头一样,都是为了找到目标应用。
接下来是为了解决乱序问题给包编的序号,以及为了确认对方已经收到发出去的包的确认编号。
接下来是一些状态位,比如SYN是发起一个连接,ACK是回复,RST是重新连接,FIN是结束连接等。TCP是面向连接的,因而双方要维护连接的状态,这些带状态位的包的发送,会引起双方的状态变更。
剩下一个是窗口大小,TCP要做流量控制,通信双方各声明一个窗口,标识自己当前能够处理的能力,别发太快,也别发太慢。

4.2.2 TCP的三次握手

TCP连接的建立,常常被称为三次握手。

A : 你好,我是A
B:你好A,我是B
A:你好B

这是一个请求-> 应答 -> 应答之应答的三个回合,A把网络包发送给B,B接收到了,但此时A并不知道B接收到了,所以B需要给A一个应答,B也要给A发送一个网络包,同时B也需要知道A接收到了这个应答的网络包,于是A需要给B发送一个应答之应答的网络包。当B收到这个应答之应答的网络包之后,这两个人的连接就算建立成功了。

除了建立连接,A和B的三次握手还为了沟通另外一件事件,就是TCP包的序号的问题。 A要告诉B,我这面发起的包的序号起始是从哪个号开始的,B同样也要告诉A,B发起的包的序号起始是从哪个号开始的。 每个连接都要有不同的序号,这是为了避免错误。

例如:A连接上B之后,给B发了1、2、3三个包,发送3的时候,连接断开了,重新连接上B之后,序号又从1开始,然后发送2,压根没有3这个包,但是上次绕路的那个3回来了,发给了B,B自然认为这是下一个包,就发生了错误。

为了解决类似的问题,每个连接都要有不同的序号,这个序号的起始序号是随着时间变化的,可以看成是一个32位的计数器,每4微秒+1。

4.2.3 TCP的四次挥手

A和B断开连接时,需要经历4次挥手的过程。

A : B,我不想玩了。
B: 哦,你不想玩了啊,我知道了。

这时,A不再发送数据,而B还要处理之前A发送的数据,还是可以发送数据的,此时B处于半关闭状态。等B处理完,B就会和A说:

B:好啊,我也不玩了,拜拜
A:好的,拜拜

4.2.4 状态机

双方建立连接时,前面说过,为了维护这个连接,双方都要维护一个状态机。

image.png 一开始,客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端口,处于 LISTEN 状态。然后客户端主动发起连接 SYN,之后处于 SYN-SENT 状态。服务端收到发起的连接,返回 SYN,并且 ACK 客户端的 SYN,之后处于 SYN-RCVD 状态。客户端收到服务端发送的 SYN 和 ACK 之后,发送 ACK 的 ACK,之后处于 ESTABLISHED 状态,因为它一发一收成功了。服务端收到 ACK 的 ACK 之后,处于 ESTABLISHED 状态,因为它也一发一收了。

四次挥手时,TCP同样设计了几个状态

1675231171(1).png

当A说“不玩了”,就进入FIN_WAIT_1状态,B收到A“不玩了”的消息后,发送知道了,B进入CLOSE_WAIT的状态。A收到B“知道了”,就进入FIN_WAIT_2的状态。如果这时B跑路,A将永远在这个状态,TCP协议里面没有对这个状态的处理。 B没有跑路,发送B也不玩了的消息给A,A回复B“知道了”,这时,A从FIN_WAIT_2状态结束。这之后,TCP要求A最后等待一段时间TIME_WAIT,这个时间是2MSL,MSL是报文最大生存时间,协议规定是2分钟,实际应用中常用的是30秒,1分钟和2分钟。

将上面两个状态的时序图综合起来,就是著名的TCP状态机。

image.png

上述图中,1-5是连接中的顺序和状态,a-f是连接断开过程中的顺序和状态。