网络学习 01
前言 此处是本人基于小林 coding 等网站进行的笔记,主要目的是在记笔记的过程中帮自己记忆。 TCP/IP 网络模型 应用层 (应用层协议 http,websocket 等) 传输层 (TCP/UDP):负责端到端通信 网络层 (IP 层):负责网络包的封装、分片、路由、转发 网络接口层:负责网络包在物理网络里的传输 Linux 网络是如何收发网络包的(待完善) 此部分博主要复习一下之前阅读过的《深入理解 linux 网络》,现在的版本是直接从小林 coding 上总结的,缺乏细节。 Linux 是如何收到网络包的 当网卡收到一个网络包,会通过 DMA 将网络包写入 ring buffer。然后触发硬中断,硬中断会暂时屏蔽终端,表示已经知道内存中有数据了,网卡在此期间再收到数据包直接写入内存就可以了。然后硬中断还会发起软中断,然后停止屏蔽终端。 内核中的 ksoftirqd 线程专门负责软中断的处理,会轮询处理数据。ksoftirq 线程会从 ring buffer 中获取一个数据帧,用 sk_buff 表示,交给网络协议栈逐层处理。 网络包首先会进入网络接口层,在这一层检查报文的合法性,然后找出网络包的协议(IPV4、IPV6),再去掉帧头帧尾交给网络层。 到了网络层,取出 IP 包,判断下一步是要转发出去还是交给上层。当确认是要交给本机上层后,就会从 IP 头里看看上一层协议的类型是 TCP 还是 UDP,接着去掉 IP 头,然后交给传输层。 传输层取出 TCP 或 UDP 头,根据四元组「源 IP、源端口、目的 IP、目的端口」作为标识,找出对应的 Socket。并把数据放到 Socket 的接收缓冲区。 应用层调用 Socket 接口,将内核的 Socket 接收缓冲区的数据拷贝到应用层缓冲区,然后唤醒用户进程。 Linux 是如何发送网络包的 应用程序会调用 Socket 发送数据包的接口。应用程序会从用户态陷入到内核态的 Socket 层,然后内核会申请一个内核态的 sk_buff 内存,将用户数据拷贝到 sk_buff,并将其加入到发送缓冲区。 网络协议栈从 Socket 发送缓冲区取下 sk_buff,并按照 TCP/IP 协议栈从上到下逐层处理。 如果是 TCP 协议,需要先 拷贝一个新的 sk_buff 副本,因为 sk_buff 后续在调用网络层,最后到达网卡发送完成的时候,这个 sk_buff 会释放掉。而 TCP 协议是支持丢失重传的,在收到对方的 ACK 之前,这个 sk_buff 不能被删除。 接着对 sk_buff 填充 TCP 头。sk_buff 头部预留了协议栈的空间,通过前移 data 指针来逐层填充协议头。 然后数据包交给网络层,网络层会选取路由(确认下一跳的 ip)、填充 IP 头、netfilter 过滤,对超过 MTU 大小的数据包进行分片。接着交给网络接口层处理。 网络接口层通过 ARP 协议获得下一跳的 MAC 地址,然后对 sk_buff 填充帧头和帧尾,然后将 sk_buff 放到网卡的发送队列中。 然后会触发软中断告诉网卡区驱动,有新数据包要发送。驱动程序会从发送队列中读取 sk_buff,将这个 sk_buff 挂到 RingBuffer 中,然后将 sk_buff 映射到网卡可访问的内存 DMA 区域,最后触发真实的发送。 当发送完成的时候,网卡会触发硬中断释放 sk_buff 内存和 ring buffer 的内存。最后,当收到这个报文的 ACK 后,传输层就会释放原始的 sk_buff。 发送网络数据涉及几次内存拷贝? 调用发送数据的系统调用时,用户数据会拷贝到 sk_buff 内存 使用 TCP 协议时,从传输层进入网络层的时候,会将 sk_buff 拷贝一个副本用于发送 当 IP 层发送发现 sk_buff 大于 MTU 时会再申请额外的 sk_buff,将原来的 sk_buff 拷贝为多个小的 sk_buff。 键入网址后发生的事情 浏览器解析 URL,生成发送给 web 服务器的请求信息 查询 DNS,获取域名的 IP 地址(DNS 有缓存) 获取 IP 后要建立 TCP 连接,经过三次握手后,就建立好连接,然后将要发送的请求信息封装为 TCP 包,TCP 负责将数据可靠交付给服务端。如果信息过长,需要进行分包。TCP 头部需要填写服务端和客户端的端口号。封装好后的包会交给下一层 IP 层。(在实际发送数据包前,如果是 https,还需要进行 tls 四次握手,在 tcp 基础上建立 tls 连接) IP 层将拿到的 TCP 包再封装为 IP 包,需要填写源地址 IP 和目的地址 IP,目的地址 IP 通过 DNS 解析得到。源 IP 在本机有多块网卡的情况下,使用路由表规则判断用哪一个网卡作为源地址 IP。 有了 IP 头部后,网络包还需要在 IP 头前面加上 MAC 头部。发送方的 MAC 头部直接从网卡的 ROM 中读取,接收方的 MAC 地址通过查路由表得到下一跳 IP,然后通过 ARP 协议在局域网内广播,获取下一跳 IP 对应的 MAC 地址(ARP 也有缓存) 封装好 MAC 包后交给网卡,网卡负责将数字信息实际转换为电信号发出去。 发送的包途径到交换机,交换机工作在二层,没有自己的 MAC 地址,它根据自己内部的 MAC 表决定发送到哪个网口,如果没有记录,则将该包广播到除接收到 MAC 帧端口的所有端口。 途径路由器的话,路由器是三层设备,会拆开 MAC 包,根据 IP 头部的目的 IP 查询路由表,判断转发目标,然后重新封装新的 MAC 包发送。 最终到达服务器后,开始按找打包顺序的逆顺序,一层一层解包:MAC 包->IP 包->TCP 包->HTTP 数据,拿到数据后,根据请求生成对应的回复信息,然后重新经历封包过程发送给客户端。 当客户端要离开时,向服务器发起 TCP 的四次挥手,断开连接。 HTTP 协议 基本概念 HTTP(HyperText Transfer Protocol)超文本传输协议。...