讲述了从 浏览器输入 URL 按下回车键,到页面在浏览器上显示这个过程中 网络内部发生了什么
ch1
生成 HTTP 请求消息
-
浏览器解析 URL 格式:协议类型 + 服务器域名/IP + 目录名 + 文件名 省略文件名case:当 URL 以 / (或者 / )都没有时,访问 默认文件(一般是 index.html ) -
生成 HTTP 请求消息 HTTP 请求消息主要包括 2 个部分:
- “对什么”:根据解析 URL 中获取,即 "目录名 + 文件名‘
- “执行什么操作”:即,方法。常用方法为
GET (只读)、POST (提交 data 给服务器) HTTP 请求消息格式:
- 第一行:请求行。即 “方法 + URI + HTTP版本”
- 第二行开始:消息头。记录额外的详细信息,如,日期、语言、压缩格式 等等
-
接受响应信息 响应消息格式:
- 第一行:响应行。即,“状态码 + 响应短语”
- 状态码:数字表示,5 大类
- 响应短语:文字表示,告知执行结果。状态码和响应短语表示的内容应该一致
- 第二行开始:
注意:每条请求消息只能写一个 URI 。如果需要获取多个文件,则需要对每个文件单独发送1条请求
所以,当一个网页有 图片等资源时,还需要单独执行 请求消息(比如,1个网页有3张图片,则需要发送 4 个请求消息)
域名解析 DNS
概念
- 域名是分层次的,越往右等级越高
- 顶级域名上面还有一个 “根级域名”,用来存放 顶级域名的信息
- 根域名服务器
- 一共 13 个 IP 地址,但是服务器远远不止 13 台(多台 根域名服务器对应一个 IP 地址)
- 根域名 DNS 服务器的信息保存在所有的 DNS 服务器中
- 任何 DNS 服务器都可以找到 根DNS服务器,从根DNS服务器就可以向下找到任意一台 DNS 服务器了
- 上级域名服务器存放的是下级域名服务器的 域名-IP 信息
DNS 过程
- 客户端访问最近的 DNS 服务器(即,客户端 TCP/IP 设置中写的 DNS 服务器地址)
- 查找 DNS 服务器中的 “缓存”,若当前 域名 命中 DNS服务器缓存,则不必再到根域DNS服务器中自顶向下查找;否则,还需要进行 3
- 本地 DNS 服务器将 DNS 查询信息转发给 根域DNS服务器
- 根域DNS服务器 返回给本地DNS服务器 “顶级域名服务器”的IP地址
- 本地 DNS 服务器将 DNS 查询信息转发给 顶级DNS服务器
- 顶级DNS服务器 返回给本地DNS服务器 “二级域名服务器”的IP地址
…
重复上述过程,直至找到一个 DNS 服务器中包含待查“域名”
Note🔥:DNS服务器中的”缓存信息“都是有 有效期的,超过有效期后会自动删除。(因为 域名 和 IP的对应关系不是永久不变的)
委托协议栈发送消息
知道了IP 地址之后,就可以委托操作系统内部的协议栈向这个目标IP地址(服务器)发送消息了
- 创建套接字;
- 连接阶段:将管道连接到服务器端的套接字上
- 收发数据(通信阶段)
- 断开阶段:断开管道并删除套接字
连接阶段
- 目的:通信双方交换控制信息(IP地址、端口号等…)
- 其实就是 “三报文握手”建立 TCP 连接
收发数据
-
将HTTP 请求消息交给协议栈
-
对较大的数据进行拆分 当发送数据超过 MTU 时,需要对数据进行 拆分; 拆分后的每个数据块要添加 “序号”; 然后,为每个数据块前面加上 TCP 头部 -
使用 ACK 确认网络包已经收到
- 单单凭着 HTTP 是无法进行网络通信的,所以需要将 HTTP请求消息 放入 TCP 中,利用 运输层的 TCP 协议来进行 可靠传输
- 使用 TCP 协议,当接受方收到一个数据包时,需要给发送方返回一个 ACK 号,表明 序号 ACK 之前的数据包 都已经正常收到了
- 但是,实际通信中 序号并不是从 1 开始的,而是使用一个 随机数 作为序号的初始值(因为,如果每次都是用 1 作为“序号 初始值”,很容易被网络攻击,被别人获取 数据包内容,这样 不安全)
- TCP 还能根据 窗口大小,进行 流量控制、拥塞避免(见 湖科大笔记)
-
接受 HTTP 响应消息
- 协议找调用
read 程序来获取响应消息 - 协议栈检查收到的数据块和 TCP 头部内容,判断是否有数据丢失,如果没有问题则返回 ACK 号;
- 然后,接受数据暂存到 接受缓存区中;
- 将数据块从接受缓存中按顺序连接起来并还原成原始的数据;
- 最后将数据交给应用程序
断开阶段
4 次挥手
下图为 TCP 收发数据的流程
IP 模块上场
TCP 模块在执行连接、收发、断开等各阶段操作时,都需要委托IP 模块将数据封装成包发送给通信对象
即,仍然套娃,把 TCP 报文作为 IP 的数据部分,并给其加上 IP 头部,构成 IP 数据包
添加 IP 地址后,相当于 "远程定位”,但是 浩瀚的网络中,如何能够到达 这一目的地呢?(类似于知道了 快递的 目的地,但是如何讲过一位位 快递小哥将包裹送到目的地呢?也即,如何找到 包裹 [数据包] 的下一个 转发点(下一位快递小哥)呢?答:需要用 MAC地址))
如何生成 IP 头部
以太网中,无法直接根据 IP 地址来区分 数据包,所以需要 添加 MAC 头部 来实现 数据包在 以太网中的 传输。
- 目的 IP 地址:根据 DNS 得到的 IP 地址;
- 源 IP 地址
- 如果只有一块网卡,因此也就只有一个IP 地址,则该 IP 地址就是 源IP地址;
- 如果有多快网卡,就稍微复杂一些了,如下
IP 地址实际上不是分配给计算机的,而不是分配给网卡的。如果有多块网卡,则有多个 IP 地址。
当主机中有多块网卡时,如何确定 IP 头部中的 源IP地址 使用哪一个IP地址?
- windows 系统可以使用
route print 查看本机“路由表” - 将 目的IP 地址和 网络掩码(Netmask)进行“逻辑与”运算;
- 如果结果和 “网络目标”匹配,则选取匹配行中 “接口 interface” 对应的 IP 地址作为 源IP地址;
- 如果结果和路由表中的“网络目标”都不匹配,则会自动匹配**“默认网关”**(即,目标地址 和 网络掩码都是
0.0.0.0 的行),选取该行中 “接口 interface” 对应的 IP地址作为 源 IP地址
UDP
还有就是 可以通过 UDP 协议来进行数据包收发。
UPD 特点:
- 面向无连接;
- 不可靠(丢包、发生错误的包 一概不管);
- 相比 TCP 更简单;
UDP 适用于:
- 发送 控制用的短数据(DNS 报文就是UDP):
- 即时通信更适合使用 UDP(比如,播放器中的 音频/视频传输、视频通话 )
MAC 模块上场
以太网 概念
总线型以太网 :
- 使用总线、基于 CSMA/CD 协议;
- 以太网中所有主机都可以收到 数据包;
- 一次只能有一台主机通信
- 使用
集线器 的以太网 :
- 集线器 本质仍然是使用总线、基于 CSMA/CD 协议;
- 以太网中所有主机都可以收到 数据包;
- 一次只能有一台主机通信
- 使用
交换机 的以太网 :
- 交换机具有“缓存”功能,不再基于 CSMA/CD;
- 交换机会利用“帧交换表”根据 目的MAC地址,将数据包从 特定的“接口”转发出去,而不是向 以太网中所有主机 广播数据包;
- 可以通信有多台主机通信
现在的以太网中,大多都采用 交换机了。
以太网经过太多版本变迁,现在认为只要满足以下 3 个性质的就是以太网:
- 将包发送到MAC 头部的接收方MAC 地址代表的目的地;
- 用发送方MAC地址识别发送方;
- 用以太类型识别包的内容
添加 MAC 头部
IP 地址相当于“远程定位”,但是在 茫茫的网络世界中,如何将 “数据包” 传输到目的地呢?即,如何每次判断 数据包 的 下一招是什么呢?
所以,需要给 IP 数据,添加一个 MAC 头部,实现数据包在 以太网中的 传输
MAC 头部
- 源 MAC 地址:从网卡的 ROM 中直接读取;
- 目的 MAC 地址:
- 首先,查询
ARP缓存 中是否有 目的IP地址。如果命中缓存,则直接返回,否则需要执行 APR 协议; - 然后,在 以太网中 广播
ARP协议 ,获取 目的IP地址 对应的 MAC 地址
Note : ARP缓存 是有 有效期的,一段时间后会自动删除!(因为 IP地址和 MAC地址的对应关系不是永久的。)
网卡 发挥作用
- 将 MAC 头部添加在 IP 头部前面后,整个 数据包就构建完成了。
- 但是,IP 模块生成的网络包只是存放在内存中的一串数字信息(即,010101…),没有办法直接发送给对方。
- 因此,我们需要将数字信息转换为电或光信号,才能在网线/光纤 上传输
而负责将 将数字信息转换为电或光信号的便是:网卡 + 网卡驱动程序
网卡 ROM 中固化的 MAC 地址会由网卡驱动程序读取并分配给 MAC 模块
网卡驱动从IP 模块获取包之后,会将其复制到网卡内的缓冲区中,并在开头加上 报头和起始帧分界符 (用于 帧定界),在末尾加上用于检测错误的帧校验序列 FCS (用于 差错检测)
最终,网卡 将此时的数据包转换为 电/光信号,利用网线转发出去
到这为止,数据包添加无数个 头部后,并由网卡 转换为 电/光信号后,才能真正离开计算机,踏上 寻找目的地的征途
网卡-接受数据包
- 将电/光信号转换为 数字信息,并放入 缓存区中;
- 检查 FCS,检测包在传输过程中是否发成错误:
- 发生错误:丢弃
- 无错误: 检测 目的MAC地址 和 自己的 MAC地址是否一致:如果一直,则将数据包放入 缓存区中;否则(不是自己的包),则 丢弃之。
- 此时,MAC 模块的工作就完成了。接下来网卡会发出 “中断” 通知计算机,让 网卡驱动程序工作
交换机
交换机并不只是简单地让信号流过,而是先接收信号并将其还原为数字信息,然后再重新转换成信号并发送出去的过程。
- 首先,信号到达网线接口,并由PHY(MAU)模块进行接收;
- PHY(MAU)模块会将网线中的信号转换为通用格式,然后传递给 MAC 模块;
- MAC 模块将信号转换为数字信息,然后通过包末尾的 FCS 校验错误,如果没有问题则存放到缓冲区中(这个过程基本和 网卡接受数据包 相同)
交换机端口的 MAC 模块 “类似于” 网卡。但仅仅是“类似”,不同点在于 交换机的端?不具有 MAC 地址
如何转发?
- 答:根据“帧交换表” + 目的 MAC 地址,判断从 哪个“端口”转发 数据包
如何维护 “帧交换表”?(即,自学习算法)
- 收发包时,将发送方 MAC 地址 和 输入端口号写入 帧交换表;
- 一段时间后,自动删除“帧交换表”中 过期的条目(因为 MAC 地址 和 端口的对应关系不是永久的,比如 换网卡了)
特殊操作:
- 当 转发的目的端口 和输入端口相同时,则直接丢弃该包(相当于兜圈了,丢之)
- 当 帧交换表中查询不到 目的MAC地址时,采用 “洪泛”(将该包从除了输入端口的所有端口转发出去)
有人会说:“这样做会发送多余的包,会不会造成网络拥塞呢?”
- 其实完全不用过于担心,因为发送了包之后目标设备会作出响应,只要返回了响应包,交换机就可以将它的地址写入地址表,下次也就不需要把包发到所有端口了。
- 局域网中每秒可以传输上千个包,多出一两个包并无大碍。
广播地址:
- MAC 地址中的
FF:FF:FF:FF:FF:FF ; - IP 地址中的
255.255.255.255 都是广播地址
交换器 vs. 集线器
- 交换机只将包转发到具有特定MAC 地址的设备连接的端口,可以同时转发多个包;
- 集线器会将输入的信号广播到所有的端口,如果同时输入多个信号就会发生碰撞,无法同时传输多路信号
路由器
路由器 vs. 交换机 :
- 路由器是基于 IP 设计,是 三层网络设备,路由器的各个端口都具有 MAC 地址和 IP 地址;
- 交换机是基于**以太网(MAC层)**设计,是 二层网络设备,交换机的端口不具有 MAC 地址;
路由器的结构
路由器分为 2 个主要模块:
- 转发模块:负责判断包的转发目的地;
- 端口模块:负责包的收发操作
可以将路由器的转发模块想象成IP 模块,将端口模块想象成网卡
通过更换网卡,计算机不仅可以支持以太网,也可以支持无线局域网,路由器也是一样。
如果路由器的端口模块安装了支持无线局域网的硬件,就可以支持无线局域网了。
此外,计算机的网卡除了以太网和无线局域网之外很少见到支持其他通信技术的品种,而路由器的端口模块则支持除局域网之外的多种通信技术,如ADSL、FTTH,以及各种宽带专线等,只要端口模块安装了支持这些技术的硬件即可
路由器工作原理
-
首先,会通过端口将发过来的包接收进来 这一步的工作过程取决于端口对应的通信技术。 对于以太网端口来说,就是按照以太网规范进行工作,而无线局域网端口则按照无线局域网的规范工作 -
转发模块会根据接收到的数据包中的 目的IP 地址,在路由表中进行查询,以此判断转发目标; -
转发模块将包转移到转发目标对应的端口,端口再按照硬件的规则将包发送出去,也就是转发模块委托端口模块将包发送出去的意思
路由聚合:
- 即,将多个子网合并成一个子网,只将 合并后的子网存入 路由表中;
- 好处:减少路由表的条目数,提高查询效率 和 可维护性
路由器会忽略主机号,只匹配网络号。
有时,也可以将某台具体计算机的地址写入路由表中:
路由器- 接收包
路由器的端口有各种不同的类型,这里我们只介绍以太网端口是如何接收包的
- 首先,信号到达网线接口部分,其中的PHY(MAU)模块和MAC 模块将信号转换为数字信息;
- 然后通过包末尾的FCS 进行错误校验,如果没问题则检查MAC 头部中的接收方MAC 地址,看看是不是发给自己的包:
- 如果是,就放到接收缓冲区中;
- 否则(接收方MAC地址和 目的MAC地址不一致),就丢弃这个包;
路由器 - 发送包
完成包接收操作之后,路由器就会丢弃包开头的MAC 头部。
MAC 头部的作用就是将包送达路由器,其中的接收方MAC 地址就是路由器端口 的MAC 地址
接下来,路由器会根据MAC 头部后方的IP 头部中的内容进行包的转发操作。
路由器转发操作分为以下几个阶段,首先 需要查询路由表判断转发目标。
1、判断转发目标
- 利用
子网掩码 + 目的 IP 地址进行“逻辑与” 运算,找到 结果和 路由表中 第一列匹配的行; - 如果成功匹配,路由器就会将网络包交给
接口列 中指定的网络接口(即,端口。也即,源 IP 地址),并转发到网关列 中指定的 IP 地址(即,目的 IP 地址。【这里可能为空,见第 2 步】); - 如果 “每一条都无法匹配”,则会转发给 “默认路由/网关”(即,子网掩码为
0.0.0.0 行对应的 “网关列”)
2、包发送操作
假设这里路由器让然是基于 以太网规则进行发送 数据包的,则需要在包前面 添加 MAC 头部
如何 判断转发目标?
- 如果路由表的网关列内容为 IP 地址,则该地址就是下一个转发目标;
- 如果路由表的网关列内容为空,则 IP 头部中的接收方 IP 地址就是下一个转发目标
找到转发目标的 IP 地址后,则需要添加 MAC 头部:
- 源 MAC 地址:路由器输出端口的 MAC 地址(见 1 中第 2 步);
- 目的 MAC 地址:根据 转发目标的 IP 地址,执行 ARP 协议,获取目的 MAC 地址
以下参考《小林coding-图解网络》
在网络包传输的过程中,源 IP 地址和 目的IP地址始终是不会改变的,**一直变化的是 MAC 地址,**因为需要 MAC 地址在 以太网内进行 两个设备之间的包传输。
为什么有了IP地址,还需要 MAC 地址?
IP 协议本身没有传输包的功能,因此包的实际传输要委托以太网来进行。
路由器是基于IP 设计的,而交换机是基于以太网设计的。
换句话说,路由器将包的传输工作委托给交换机来进行。
当然,这里讲的内容只适用于原原本本实现IP 和以太网机制的纯粹的路由器和交换机,实际的路由器有内置交换机功能的,比如用于连接互联网的家用路由器就属于这一种,对于这种路由器,上面内容可能就不适用了。但是,如果把这种“不纯粹”的路由器拆分成“纯粹”的路由器和“纯粹”的交换机,则它们各自都适用上面的内容。
IP 并不是委托以太网将包传输到最终目的地,而是传输到下一个路由器。
- 在创建MAC 头部时,也是从IP 的路由表中查找出下一个路由器的IP 地址;
- 然后,通过ARP 查询出MAC 地址,然后将MAC 地址写入MAC 头部中的
这表示IP 对以太网的委托只是将包传输到下一个路由器就行了。
当包到达下一个路由器后,下一个路由器又会重新委托以太网将包传输到再下一个路由器。
随着这一过程反复执行,包就会最终到达IP 的目的地,也就是通信的对象。
IP 本身不负责包的传输,而是委托各种通信技术将包传输到下一个路由器,这样的设计是有重要意义的:
- 即,可以根据需要灵活运用各种通信技术
- 这也是IP 的最大特点。正是有了这一特点,我们才能够构建出互联网这一规模巨大的网络。
|