从零到一手写操作系统(十一、网络 1)从URL到网卡,网络数据如何流动?)
如果追忆会荡起涟漪,那么今天的秋红落叶和晴空万里都归你
https://aeneag.xyz
微信公众号:技术乱舞
艾恩凝
手写操作系统目录
输入 URL,从一个请求到响应都发生了什么事?
- 常规的网络交互过程是从客户端发起网络请求,用户态的应用程序(浏览器)会生成 HTTP 请求报文、并通过 DNS 协议查找到对应的远端 IP 地址。
- ** 在套接字生成之后进入内核态,浏览器会委托操作系统内核协议栈中的上半部分,也就是 TCP/UDP 协议发起连接请求。**
- 然后经由协议栈下半部分的 IP 协议进行封装,使数据包具有远程定位能力。
- 经过 MAC 层处理,找到接收方的目标 MAC 地址。
- 最终数据包在经过网卡转化成电信号经过交换机、路由器发送到服务端,服务端经过处理拿到数据,再通过各种网络协议把数据响应给客户端。
- 客户端拿到数据进行渲染。
- 客户端和服务端之间反复交换数据,客户端的页面数据就会发生变化。
TCP/IP 层的体系结构
应用层 用户输入:在浏览器中输入 URL
**我们以输入aeneag.xyz为例,首先浏览器会判断出这是一个合法的 URL,并且会补全为 **https://aeneag.xyz
其中 https 为协议,aeneag.xyz为网络地址,每个网络栏的地址都符合通用 URI 的语法。URI 一般语法由五个分层序列组成。
1URI = scheme:[//authority]path[?query][#fragment]
2
3 URI = 方案:[//授权]路径[?查询][#片段ID]
接着,浏览器从 URL 中会提取出网络的地址,也叫做主机名(host),一般主机名可以为域名或 IP 地址,此处使用域名。
网络请求前:查看浏览器缓存
在请求发出之前,浏览器首先会检查保存在本地计算机中的缓存,如果访问过当前的 URL,会先进入缓存中查询是否有要请求的文件。此时存在的缓存有路由器缓存、DNS 缓存、浏览器缓存、Service Worker、Memory Cache、Disk Cache、Push Cache、系统缓存等。
在这里我们看一下系统缓存,如果在浏览器缓存里没有命中缓存,浏览器会做一个系统调用获得系统缓存中的记录,就是我们的 gethostbyname 方法,它的作用是通过域名获取 IP 地址。这个方法会返回如下结构。
1struct hostent
2 {
3 char *h_name;// 主机的别名.www.cosmos.com就是google他自己的别名
4 char **h_aliases;// 主机ip地址的类型,到底是ipv4(AF_INET),还是pv6(AF_INET6)
5 int h_addrtype;// 主机ip地址的长度
6 int h_length;// 主机ip地址的长度
7 char **h_addr_list; // 主机的ip地址,注意,这个是以网络字节序存储的
8 #define h_addr h_addr_list[0] 这个函数,是将类型为af的网络地址结构src,转换成主机序的字符串形式,存放在长度为cnt的字符串中。返回指向dst的一个指针。如果函数调用错误,返回值是NULL
9 };
如果没有访问过当前的 URL,就会跳过缓存这一步,这时我们就会进入网络操作了。
域名解析:DNS
浏览器就会生成对应的 HTTP 请求,这时浏览器需要委托操作系统将 HTTP 报文发送到对应的服务端。在发送消息之前,还有一个工作需要做,就是查找服务端的 IP 地址,因为操作系统在发送消息时,必须知道对方的 IP 地址才可以发送。
DNS解析 > 浏览器DNS缓存 > hosts文件 > 本地DNS服务器 > ISP DNS服务器
操作系统协议栈(传输层和网络层)
根据 URL 拿到需要请求的唯一地址了,接下来就要委托操作系统将 HTTP 报文发送出去了,这个过程由操作系统中的协议栈负责处理。
TCP/IP 协议栈是现在使用最广泛的网络协议栈,Internet 就是建立在 TCP/IP 协议栈基础上的。
协议栈内部分为几部分,分别承担着不同的作用。协议栈的上半部分负责和应用层通过套接字(Socket)进行交互,它可以是 TCP 协议或 UDP 协议。应用层会委托协议栈的上部分完成收发数据的工作;而协议栈的下半部分则负责把数据发送给到指定方的 IP 协议,由 IP 协议连接下层的网卡驱动。
可靠性传输:建立 TCP 连接
这里进行三次握手,详情就不叙述了
TCP 层封装好了数据包,会将这个 TCP 数据包向下层发送,而 TCP 层的下层就是 IP 层。
目的地定位:IP 层
TCP在维护状态的过程中,都需要委托 IP 层将数据封装,发送和处理网络数据包进入网络层。IP 协议是 TCP/IP 协议栈的核心,IP 协议中规定了在 Internet 上进行通信时应遵循的规则,包括 IP 数据包应如何构成、数据包的路由等,而 IP 层实现了网络上的点对点通信。
- 数据包校验和检验2. 防火墙对数据包过滤3.IP 选项处理4. 数据分片和重组5. 接收、发送和前送
IP 层被设计成三个部分,分别是 IP 寻址、路由和分包组包
P 地址及相关信息组装成一个 IP 头
点对点传输:MAC(链路层)
MAC 地址指的就是计算机网卡的物理地址(Physical Address),MAC 地址被固化到网卡中,用来标识一个网络设备。MAC 地址是唯一且无重复的,由国际标准化组织分配,用来确保网络中的每个网卡是唯一的。
网络数据在 IP 层中加上 IP 头后,形成了 IP 包,现在进入 MAC 层了,我们就需要对 IP 包加上 MAC 头,这个 MAC 头包括发送方的 MAC 头和接收方的 MAC 头,用于两个物理地址点对点的传输;此外还有一个头部字段为协议类型,在常规的 TCP/IP 协议中,MAC 头的协议类型只有 IP 和 ARP 两种。
MAC 头格式如下所示。
电信号的出口:网卡(物理层)
MAC 数据包会交给网卡驱动程序,而网卡驱动程序会将 MAC 数据包写入网卡的缓冲区(网卡上的内存).然后,网卡会在 MAC 数据包的起止位置加入起止帧和校验序列,最后网卡会将加入起止帧和校验序列的 MAC 数据包转化为电信号,发送出去。
客户端服务端的持续数据交换(应用层)
数据终于通过网卡离开了计算机,进入到局域网,通过局域网中的设备,集线器、交换机和路由器等,数据会进入到互联网,最终到达目标服务器。
接着,服务器就会先取下数据包的 MAC 头部,查看是否匹配自己 MAC 地址。然后继续取下数据包的 IP 头,数据包中的目标 IP 地址和自己的 IP 地址匹配,再根据 IP 头中协议项,知道自己上层是 TCP 协议。
之后,还要继续取下数据包 TCP 的头。完成一系列的顺序校验和状态变更后,TCP 头部里面还有端口号,此时我们的 HTTP 的 server 正在监听这个端口号,就把数据包再发给对应的 HTTP 进程。
过程为
手写操作系统目录
则移山填海之难,
终有成功之日!
——孙文