Contents

计算机网络-小林coding-基础篇

本系列笔记为作者在跟随小林coding学习的时候做的笔记。感谢小林大大。加上自己的笔记

TCP/IP 网络模型有哪几层?

TCP/IP 网络分 4 层:应用层,传输层,网络层和网络接口层

ISO为7层,传统网络架构为5层,将数据链路层的物理层分离了出来单独作为一层。

传统网络分层为5层:应用层,传输层,网络层,数据链路层和物理层

附上网络协议层级图

/images/计算机网络/小林coding/网络协议层级图.png
网络层级图

键入网址到网页显示,期间发生了什么

HTTP

浏览器解析 URL字符串: 协议类型://域名或者IP:端口号/文件路径

端口号省略时默认是协议对应的默认端口,比如http是80

没有路径名则访问index.html或default.html

根据这些信息生成 HTTP 请求消息

DNS查询

应用层,传输层,网络层和网络接口层发送之前需要查询服务器域名对应的 IP 地址。

域名由.分割,越靠右的位置表示其层级越高。域名的层级关系类似一个树状结构:

  • 根 DNS 服务器(.)
  • 顶级 DNS 服务器(.com)
  • 权威 DNS 服务器(server.com)

微信公众号 DNS解析的具体过程

首先是查询浏览器缓存和操作系统缓存以及host解析,没查到再进行dns域名解析

域名解析的工作流程

  1. 客户端发出 DNS 请求给本地设置的 DNS 服务器地址
  2. 本地域名服务器查询缓存,找到 www.server.com,则直接返回 IP 地址。否则本地 DNS 会去问它的根域名服务器
  3. 根 DNS 返回给本地域名服务器 .com 顶级域名服务器地址
  4. 本地域名服务器和返回的服务器地址重复2,3步,直到找到权威域名服务器。
  5. 权威域名服务器直接返回IP给本地域名服务器
  6. 本地域名服务器将IP返回给客户端

通常客户端到域名服务器是不可靠无连接的UDP通信,域名服务器之间使用可靠有连接的TCP通信进行迭代查询

操作系统协议栈

获取 IP 后,操作系统中的协议栈处理和发送数据包(传统网络架构中的传输层到数据链路层。物理层由网卡驱动接管)。

应用程序(浏览器)通过调用 Socket 库,来委托协议栈工作。

TCP

源端口号和目标端口号寻址

包的序号解决包乱序的问题

状态位:改变协议状态。

窗口大小做流量控制

协议规定了自己的拥塞控制行为

TCP 传输数据之前,要先三次握手建立连接

https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost4/%E7%BD%91%E7%BB%9C/TCP%E4%B8%89%E6%AC%A1%E6%8F%A1%E6%89%8B.drawio.png

查看 TCP 的连接状态:netstat -napt

MSS:TCP包载荷的最大长度

MTU:一个IP包的最大长度,一般为1500字节

https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/%E9%94%AE%E5%85%A5%E7%BD%91%E5%9D%80%E8%BF%87%E7%A8%8B/13.jpg

IP

https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/%E9%94%AE%E5%85%A5%E7%BD%91%E5%9D%80%E8%BF%87%E7%A8%8B/14.jpg

源地址 IP 和 目标地址 IP

传输层协议的协议号

路由数据包时根据路由表规则,来判断哪一个网卡作为源地址 IP

route -n 命令查看当前系统的路由表(推荐ip系列的命令 ip routes)

路由数据包流程:路由表从上往下将包目的ip和掩码与运算,结果和目的网段相同就匹配上,使用匹配的网卡(端口)进行转发。通常最后一个条目的目的网段和子网掩码都是0.0.0.0,称为默认网关,当上面的都不匹配的时候就发送到这个网卡接口,该条目的Gateway就是默认网关ip地址。发送出数据包时,当Gateway为0.0.0.0时表示该网段跟主机是直连的,链路层将目的ip对应的MAC作为链路层包头的MAC,否则使用Gateway 的MAC。

MAC

https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost/%E8%AE%A1%E7%AE%97%E6%9C%BA%E7%BD%91%E7%BB%9C/%E9%94%AE%E5%85%A5%E7%BD%91%E5%9D%80%E8%BF%87%E7%A8%8B/18.jpg

MAC 包头里需要发送方 MAC 地址和接收方目标 MAC 地址,用于两点之间的传输

MAC 包头的协议类型只使用:0800 : IP 协议;0806 : ARP 协议

发送方的 MAC 地址是在网卡生产时写入到 ROM 里的,只需要将这个值读取出来写入到 MAC 头部。

接收方的 MAC 地址需要 ARP 协议来获取。

ARP 协议会在以太网(局域网)中广播ip地址,接收到回应后将MAC写入ARP缓存(缓存时间为几分钟)

发包时:

  • ARP 缓存已经保存了对方的 MAC 地址,直接使用 ARP 缓存中的地址。
  • ARP 缓存中不存在对方 MAC 地址时,发送 ARP 广播查询。

arp -a查看 ARP 缓存的内容

网卡

我们需要将数字信息转换为电信号,才能在网线上传输,由网卡负责。网卡驱动程序控制网卡。

网卡驱动获取网络包之后,会将其复制到网卡内的缓存区中,接着会在其开头加上报头和起始帧分界符,在末尾加上用于检测错误的帧校验序列。

  • 起始帧分界符是一个用来表示包起始位置的标记
  • 末尾的 FCS(帧校验序列)用来检查包传输过程是否有损坏

交换机

将网络包原样转发到目的地。也称为二层网络设备(即传统网络架构中的数据链路层,不涉及网络层及以上数据包的修改)

交换机的包接收操作:交换机接收电信号,将电信号转换为数字信号,通过包末尾的 FCS 校验错误,如果没问题则放到缓冲区,根据 MAC 地址表查找 MAC 地址,然后将信号发送到相应的端口。当 MAC 地址表找不到指定的 MAC 地址,将包转发到除了源端口之外的所有端口。

交换机的 MAC 地址表主要包含两个信息:一个是设备的 MAC 地址,另一个是该设备连接在交换机的哪个端口上。

对于主机而言,只有目的地址跟自己的MAC一致包才接收,忽略其他包

广播地址(全1):

  • MAC 地址中的 FF:FF:FF:FF:FF:FF
  • IP 地址中的 255.255.255.255

路由器

路由器是基于 IP 设计的,俗称三层网络设备(即传统网络架构中的网络层),路由器的各个端口都具有 MAC 地址和 IP 地址

路由流程见上面IP层

路由器的端口都具有 MAC 地址,只接收与自身地址匹配的包,遇到不匹配的包则直接丢弃

互相扒皮 —— 服务器 与 客户端

逐层协议分析包头。链路层接收和自己的 MAC 地址符合的包。网络层接收和自己的IP地址符合的IP包。根据IP头读取传输层协议。TCP会检查首部校验和序列号并返回ACK,UDP只检查首部校验和。读取传输层端口号,并将传输层载荷发送给进程。

Linux 系统是如何收发网络包的?

网络模型

OSI7层,传统5层,TCP/IP4层

Linux 网络协议栈

https://cdn.xiaolincoding.com/gh/xiaolincoder/ImageHost3@main/%E6%93%8D%E4%BD%9C%E7%B3%BB%E7%BB%9F/%E6%B5%AE%E7%82%B9/%E5%8D%8F%E8%AE%AE%E6%A0%88.png
  • 应用程序需要通过系统调用,来跟 Socket 层进行数据交互;
  • Socket 层的下面就是传输层、网络层和网络接口层;
  • 最下面的一层,则是网卡驱动程序和硬件网卡设备;

Linux 接收网络包的流程

当网卡接收到一个网络包后,会通过 DMA 技术,将网络包写入到指定的内存地址,也就是写入到 Ring Buffer,缓存满了就会触发中断唤醒数据接收的服务程序,然后 poll 的方法来轮询数据

硬件中断处理函数:先「暂时屏蔽中断」,表示已经知道内存中有数据了。发起「软中断」,然后恢复刚才屏蔽的硬件中断。

硬件中断处理函数做的事情很少,主要耗时的工作都交给软中断处理函数了。

软中断的处理:当 ksoftirqd 内核线程收到软中断后,就会来轮询处理数据。ksoftirqd 线程会从 Ring Buffer 中获取一个数据帧,用 sk_buff 表示,从而可以作为一个网络包交给网络协议栈进行逐层处理。

发送网络数据的时候,涉及几次内存拷贝操作?

第一次,调用发送数据的系统调用的时候,内核会申请一个内核态的 sk_buff 内存,将用户待发送的数据拷贝到 sk_buff 内存,并将其加入到发送缓冲区。

第二次,在使用 TCP 传输协议的情况下,从传输层进入网络层的时候,每一个 sk_buff 都会被克隆一个新的副本出来。副本 sk_buff 会被送往网络层,等它发送完的时候就会释放掉,然后原始的 sk_buff 还保留在传输层,目的是为了实现 TCP 的可靠传输,等收到这个数据包的 ACK 时,才会释放原始的 sk_buff 。

第三次,当 IP 层发现 sk_buff 大于 MTU 时才需要进行。会再申请额外的 sk_buff,并将原来的 sk_buff 拷贝为多个小的 sk_buff。

 |