计算机网络学习笔记 ---- 基础篇

1 基础

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

TCP/IP 网络通常是由上到下分成 4 层,分别是应用层,传输层,网络层和网络接口层。
在这里插入图片描述

在这里插入图片描述
网络接口层的传输单位是帧(frame),IP 层的传输单位是包(packet),TCP 层的传输单位是段(segment),HTTP 的传输单位则是消息或报文(message)。但这些名词并没有什么本质的区分,可以统称为数据包。

1.1.1 应用层

为最上层,即用户可直接接触到。只专注于为用户提供应用功能(如HTTP、FTP、Telnet、DNS、SMTP等)。工作在操作系统中的用户态,传输层及以下则工作在内核态。

1.1.2 传输层

应用层的数据包会传给传输层,传输层(Transport Layer)是为应用层提供网络支持的。用到两个协议:TCP、UDP

TCP 的全称叫传输控制协议(Transmission Control Protocol),
大部分应用使用的正是 TCP 传输层协议,比如 HTTP 应用层协议。
TCP 相比 UDP 多了很多特性,比如流量控制、超时重传、拥塞控制等,这些都是为了保证数据包能可靠地传输给对方。

UDP 只负责发送数据包,不保证数据包是否能抵达对方,但它实时性相对更好,传输效率也高。
UDP 也可以实现可靠传输,把 TCP 的特性在应用层上实现就可以,

当传输层的数据包大小超过 MSS(TCP 最大报文段长度) ,就要将数据包分块。需要重发时只需重发该分块即可。

在 TCP 协议中,每个分块称为一个 TCP 段(TCP Segment)。传输层负责把数据包传给应用,通过编号将应用区分开来,即端口。

1.1.3 网络层

实际的传输功能(在错综复杂的网络环节中,对各种各样的路径和节点进行选择)由网络层(Internet Layer)完成。

网络层最常使用的是 IP 协议(Internet Protocol),IP 协议会将传输层的报文作为数据部分,再加上 IP 报头组装成 IP 报文,如果 IP 报文大小超过 MTU(以太网中一般为 1500 字节)就会再次进行分片,得到一个即将发送到网络的 IP 报文。

在这里插入图片描述

用 IP 地址给设备进行编号,对于 IPv4 协议, IP 地址共 32 位,分成了四段(比如,192.168.100.1),每段是 8 位。

将 IP 地址分成两种意义:

· 一个是网络号,负责标识该 IP 地址是属于哪个「子网」的;
· 一个是主机号,负责标识同一「子网」下的不同主机;

配合子网掩码才能算出 IP 地址 的网络号和主机号
在这里插入图片描述
寻址
将 ip地址 和 子网掩码 进行按位与运算,就可以得到网络号;
将 子网掩码 取反后与I P地址 进行进行按位与运算,就可以得到主机号。

路由
当数据包到达一个网络节点,就需要通过路由算法决定下一步走哪条路径。

在这里插入图片描述

IP 协议的寻址作用是告诉我们去往下一个目的地该朝哪个方向走,路由则是根据「下一个目的地」选择路径。寻址更像在导航,路由更像在操作方向盘。

1.1.4 网络接口层

生成了 IP 头部之后,接下来要交给网络接口层(Link Layer)在 IP 头部的前面加上 MAC 头部,并封装成数据帧(Data frame)发送到网络上。

IP 头部中的接收方 IP 地址表示网络包的目的地,通过这个地址我们就可以判断要将包发到哪里,但在以太网中不可使用。

以太网就是一种在「局域网」内,把附近的设备连接起来,使它们之间可以进行通讯的技术。MAC 头部是以太网使用的头部,它包含了接收方和发送方的 MAC 地址等信息,我们可以通过 ARP 协议获取对方的 MAC 地址。

=====================================================
网络接口层主要为网络层提供「链路级别」传输的服务,负责在以太网、WiFi 这样的底层网络上发送原始数据包,工作在网卡这个层次,使用 MAC 地址来标识网络上的设备。

1.2 键入网址到网页显示

网络拓扑模型在这里插入图片描述

1.2.1 HTTP

浏览器做的第一步工作就是要对 URL 进行解析,从而生成发送给 Web 服务器的请求信息。

在这里插入图片描述
在这里插入图片描述
在这里插入图片描述
URL 实际上是请求服务器里的文件资源。当没有路径名时,就代表访问根目录下事先设置的默认文件,也就是 /index.html 或者 /default.html

第二步 根据Web服务器和文件名,生成HTTP请求消息

在这里插入图片描述
在这里插入图片描述

1.2.2 DNS

通过浏览器解析 URL 并生成 HTTP 消息后,需要委托操作系统将消息发送给 Web 服务器。但在发送之前,需要查询服务器域名对应的 IP 地址。

DNS 中的域名都是用句点来分隔的,比如 www.server.com,这里的句点代表了不同层次之间的界限。在域名中,越靠右的位置表示其层级越高。

实际上域名最后还有一个点,比如 www.server.com.,这个最后的一个点代表根域名。也就是,. 根域是在最顶层,它的下一层就是 .com 顶级域,再下面是 server.com。

域名的层级关系类似一个树状结构:
在这里插入图片描述

DNS解析过程:

在这里插入图片描述
浏览器会先看自身有没有对这个域名的缓存,如果有,就直接返回,如果没有,就去问操作系统,操作系统也会去看自己的缓存,如果有,就直接返回,如果没有,再去 hosts 文件看,也没有,才会去问「本地 DNS 服务器」。

1.2.3 协议栈(指南)

通过 DNS 获取到 IP 后,就可以把 HTTP 的传输工作交给操作系统中的协议栈。

在这里插入图片描述

应用程序(浏览器)通过调用 Socket 库,来委托协议栈工作。
协议栈的上半部分有两块,分别是负责收发数据的 TCP 和 UDP 协议,这两个传输协议会接受应用层的委托执行收发数据的操作

协议栈的下半部分用 IP 协议控制网络包收发操作,在互联网上传数据时,数据会被切分成一块块的网络包,而将网络包发送给对方的操作就是由 IP 负责的。

其中,IP协议中还包括 ICMP 协议和 ARP 协议。

· ICMP 用于告知网络包传送过程中产生的错误以及各种控制信息。
· ARP 用于根据 IP 地址查询相应的以太网 MAC 地址。

IP 下面的网卡驱动程序负责控制网卡硬件,而最下面的网卡则负责完成实际的收发操作,也就是对网线中的信号执行发送和接收操作。

1.2.4 TCP

TCP 报文头部的格式:

在这里插入图片描述
状态位:

SYN :发起连接,
ACK :回复,
RST :重新连接,
FIN :结束连接,
PSH :有DATA数据传输,
RST :连接重置。

TCP连接:三次握手
保证双方都有发送和接收的能力

时序图:

在这里插入图片描述

· 一开始,客户端和服务端都处于 CLOSED 状态。先是服务端主动监听某个端口,处于 LISTEN 状态。

· 然后客户端主动发起连接 SYN,之后处于 SYN-SENT 状态。

· 服务端收到发起的连接,返回 SYN,并且 ACK 客户端的 SYN,之后处于 SYN-RCVD 状态。

· 客户端收到服务端发送的 SYN 和 ACK 之后,发送对 SYN 确认的 ACK,之后处于 ESTABLISHED 状态,因为它一发一收成功了。

· 服务端收到 ACK 的 ACK 之后,处于 ESTABLISHED 状态,因为它也一发一收了。

TCP 分割数据
如果 HTTP 请求消息比较长,超过了 MSS 的长度,这时 TCP 就需要把 HTTP 的数据拆解成一块块的数据发送。
在这里插入图片描述

· MTU:一个网络包的最大长度,以太网中一般为 1500 字节。
· MSS:除去 IP 和 TCP 头部之后,一个网络包所能容纳的 TCP 数据的最大长度。

数据会被以 MSS 的长度为单位进行拆分,拆分出来的每一块数据都会被放进单独的网络包中。也就是在每个被拆分的数据加上 TCP 头信息,然后交给 IP 模块来发送数据。

在这里插入图片描述

TCP报文生成

TCP 协议里面会有两个端口,一个是浏览器监听的端口(通常是随机生成的),一个是 Web 服务器监听的端口(HTTP 默认端口号是 80, HTTPS 默认端口号是 443)。

在双方建立了连接后,TCP 报文中的数据部分就是存放 HTTP报文(HTTP 头部 + 数据),组装好 TCP 报文之后,就需交给下面的网络层处理。

1.2.5 IP

TCP 模块在执行连接、收发、断开等各阶段操作时,都需要委托 IP 模块将数据封装成网络包发送给通信对象。

IP 报文头部格式

在这里插入图片描述
当存在多个网卡时,在填写源地址 IP 时,就需要根据路由表规则,来判断哪一个网卡作为源地址 IP。

在这里插入图片描述

IP报文生成

在这里插入图片描述

1.2.6 MAC

生成了 IP 头部之后,接下来网络包还需要在 IP 头部的前面加上 MAC 头部。

MAC包头格式

MAC 头部是以太网使用的头部,它包含了接收方和发送方的 MAC 地址等信息。
在这里插入图片描述
一般在 TCP/IP 通信里,MAC 包头的协议类型只使用:

0800 : IP 协议
0806 : ARP 协议

发送方的 MAC 地址获取:读取 ROM (在网卡生产时写入到 ROM 里的) 写入到 MAC 头部。

接收方的 MAC 地址获取

先得搞清楚应该把包发给谁,这个只要查一下路由表就知道了。在路由表中找到相匹配的条目,然后把包发给 Gateway 列中的 IP 地址就可以了。

然后需要 ARP 协议找到路由器的 MAC 地址。
ARP 协议会在以太网中以广播的形式询问,同一子网内的路由器会回答,由此得到MAC地址写入头部,同时本次查询的结果会放到一块叫做 ARP 缓存的内存空间留着以后用。

即,在发包时:

· 先查询 ARP 缓存,如果其中已经保存了对方的 MAC 地址,就不需要发送 ARP 查询,直接使用 ARP 缓存中的地址。

· 而当 ARP 缓存中不存在对方 MAC 地址时,则发送 ARP 广播查询。

至此网络包报文生成

1.2.7 网卡(出口)

网络包只是存放在内存中的一串二进制数字信息,需要进行转换。

负责将数字信息转换成电信号。控制网卡需要靠网卡驱动程序

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

在这里插入图片描述

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

最后网卡会将包转为电信号,通过网线发送出去。

1.2.8 交换机(送别者)

交换机的设计是将网络包原样转发到目的地。交换机工作在 MAC 层,也称为二层网络设备。

交换机的包接收操作

首先,电信号到达网线接口,交换机里的模块进行接收,
接下来交换机里的模块将电信号转换为数字信号。
然后通过包末尾的 FCS 校验错误,如果没问题则放到缓冲区。

这部分操作基本和计算机的网卡相同,但交换机的工作方式和网卡不同。

计算机网卡具有MAC地址,收到包后会进行核对,如果不是发给自己的则丢弃;
交换机端口不具有MAC地址,会直接接收所有包并放入缓冲区

将包存入缓冲区后,需要查询该包的接收方 MAC 地址是否在 MAC 地址表中。
交换机的 MAC 地址表主要包含两个信息:

· 一个是设备的 MAC 地址,
· 另一个是该设备连接在交换机的哪个端口上。

在这里插入图片描述
交换机根据 MAC 地址表查找 MAC 地址,然后将信号发送到相应的端口。

地址表中找不到指定的 MAC 地址。
这可能是因为具有该地址的设备还没有向交换机发送过包,或者这个设备一段时间没有工作导致地址被从地址表中删除了。
这种情况下,交换机无法判断应该把包转发到哪个端口,只能将包转发到除了源端口之外的所有端口上,只有相应的接收者才接收包,而其他设备则会忽略这个包。

如果接收方 MAC 地址是一个广播地址,那么交换机会将包发送到除源端口之外的所有端口。以下两个属于广播地址:

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

1.2.9 路由器(出境大门)

网络包经过交换机之后,现在到达了路由器,并在此被转发到下一个路由器或目标设备。转发的工作原理和交换机类似,也是通过查表判断包转发的目标。

在具体的操作过程上,路由器和交换机是有区别的。

· 因为路由器是基于 IP 设计的,俗称三层网络设备,路由器的各个端口都具有 MAC 地址和 IP 地址;
· 而交换机是基于以太网设计的,俗称二层网络设备,交换机的端口不具有 MAC 地址。

当转发包时,首先路由器端口会接收发给自己的以太网包,然后路由表查询转发目标,再由相应的端口作为发送方将以太网包发送出去。

路由器 包接收操作

首先,电信号到达网线接口部分,路由器中的模块会将电信号转成数字信号,然后通过包末尾的 FCS 进行错误校验。

如果没问题则检查 MAC 头部中的接收方 MAC 地址,如果是发给自己的包就放到接收缓冲区中,否则就丢弃这个包。

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

查询路由表确定输出端口

完成包接收操作之后,路由器就会去掉包开头的 MAC 头部。

MAC 头部的作用就是将包送达路由器,其中的接收方 MAC 地址就是路由器端口的 MAC 地址。

接下来,路由器会根据 IP 头部中的内容进行包的转发操作,转发操作分为几个阶段:

首先是查询路由表判断转发目标。实在找不到匹配路由时,就会选择默认路由,路由表中子网掩码为 0.0.0.0 的记录表示「默认路由」。
在这里插入图片描述

路由器的发送操作

首先,我们需要根据路由表的网关列判断对方的地址。

· 如果网关是一个 IP 地址,则这个IP 地址就是我们要转发到的目标地址,还未抵达终点,还需继续需要路由器转发。
· 如果网关为空,则 IP 头部中的接收方 IP 地址就是要转发到的目标地址,也是就终于找到 IP 包头里的目标地址了,说明已抵达终点。

知道对方的 IP 地址之后,接下来需要通过 ARP 协议根据 IP 地址查询 MAC 地址,并将查询的结果作为接收方 MAC 地址。

接下来是发送方 MAC 地址字段,填写输出端口的 MAC 地址。还有一个以太类型字段,填写 0800 (十六进制)表示 IP 协议。

网络包完成后,接下来会将其转换成电信号并通过端口发送出去。

发送出去的网络包会通过交换机到达下一个路由器。由于接收方 MAC 地址就是下一个路由器的地址,所以交换机会根据这一地址将包传输到下一个路由器。

1.2.10 服务器 与 客户端

在这里插入图片描述

1.3 Linux系统如何收发网络包?

1.3.1 网络模型

OSI 网络模型,该模型主要有 7 层,分别是应用层、表示层、会话层、传输层、网络层、数据链路层以及物理层:

· 应用层,负责给应用程序提供统一的接口;
· 表示层,负责把数据转换成兼容另一个系统能识别的格式;
· 会话层,负责建立、管理和终止表示层实体之间的通信会话;
· 传输层,负责端到端的数据传输;
· 网络层,负责数据的路由、转发、分片;
· 数据链路层,负责数据的封帧和差错检测,以及 MAC 寻址;
· 物理层,负责在物理网络中传输数据帧;

只是概念理论上的分层,并没有提供具体的实现方案。

TCP/IP 网络模型,共有 4 层,分别是应用层、传输层、网络层和网络接口层:

· 应用层,负责向用户提供一组应用程序,比如 HTTP、DNS、FTP 等;
· 传输层,负责端到端的通信,比如 TCP、UDP 等;
· 网络层,负责网络包的封装、分片、路由、转发,比如 IP、ICMP 等;
· 网络接口层,负责网络包在物理网络中的传输,比如网络包的封帧、 MAC 寻址、差错检测,以及通过网卡传输网络帧等;

在这里插入图片描述
常说的七层和四层负载均衡,是用 OSI 网络模型来描述的,七层对应的是应用层,四层对应的是传输层。

1.3.2 Linux 网络协议栈

在这里插入图片描述

· 应用程序需要通过系统调用,来跟 Socket 层进行数据交互;
· Socket 层的下面就是传输层、网络层和网络接口层;
· 最下面的一层,则是网卡驱动程序和硬件网卡设备;

1.3.3 Linux 接收网络包的流程

网卡是计算机里的一个硬件,专门负责接收和发送网络包。
当网卡接收到一个网络包后,会通过 DMA 技术,将网络包写入到 Ring Buffer(一个环形缓冲区),接着就会告诉操作系统这个网络包已经到达。

触发中断

最简单的一种方式就是触发中断,也就是每当网卡收到一个网络包,就触发一个中断告诉操作系统。

Linux 内核在 2.6 版本中引入了 NAPI 机制,它是混合「中断和轮询」的方式来接收网络包,它的核心概念就是首先采用中断唤醒数据接收的服务程序,然后 poll 的方法来轮询数据。

当有网络包到达时,会通过 DMA 技术,将网络包写入到指定的内存地址,接着网卡向 CPU 发起硬件中断,当 CPU 收到硬件中断请求后,根据中断表,调用已经注册的中断处理函数。

硬件中断处理函数会做如下的事情:

· 需要先「暂时屏蔽中断」,表示已经知道内存中有数据了,告诉网卡下次再收到数据包直接写内存就可以了,不要再通知 CPU 了,这样可以提高效率,避免 CPU 不停的被中断。
· 接着,发起「软中断」,然后恢复刚才屏蔽的中断。

至此,硬件中断处理函数的工作就已经完成。

软中断处理

内核中的 ksoftirqd 线程专门负责软中断的处理,当 ksoftirqd 内核线程收到软中断后,就会来轮询处理数据。

ksoftirqd 线程会从 Ring Buffer 中获取一个数据帧,用 sk_buff 表示,从而可以作为一个网络包交给网络协议栈进行逐层处理。

网络协议栈

在这里插入图片描述

1.3.4 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 的一个拷贝,等收到 ACK 再真正删除。

接着,对 sk_buff 填充 TCP 头。

sk_buff 可以表示各个层的数据包,在应用层数据包叫 data,在 TCP 层我们称为 segment,在 IP 层我们叫 packet,在数据链路层称为 frame。

只用 sk_buff 一个结构体来描述所有的网络包,通过调整 sk_buff 中 data 的指针,比如:

· 当接收报文时,从网卡驱动开始,通过协议栈层层往上传送数据报,通过增加 skb->data 的值,来逐步剥离协议首部。
· 当要发送报文时,创建 sk_buff 结构体,数据缓存区的头部预留足够的空间,用来填充各层首部,在经过各下层协议时,通过减少 skb->data 的值来增加协议首部。

至此,传输层的工作也就都完成了。

然后交给网络层,在网络层里会做这些工作:选取路由(确认下一跳的 IP)、填充 IP 头、netfilter 过滤、对超过 MTU 大小的数据包进行分片。处理完这些工作后会交给网络接口层处理。

网络接口层会通过 ARP 协议获得下一跳的 MAC 地址,然后对 sk_buff 填充帧头和帧尾,接着将 sk_buff 放到网卡的发送队列中。

这一些工作准备好后,会触发「软中断」告诉网卡驱动程序,这里有新的网络包需要发送,驱动程序会从发送队列中读取 sk_buff,将这个 sk_buff 挂到 RingBuffer 中,接着将 sk_buff 数据映射到网卡可访问的内存 DMA 区域,最后触发真实的发送。

当数据发送完成以后,其实工作并没有结束,因为内存还没有清理。当发送完成的时候,网卡设备会触发一个硬中断来释放内存,主要是释放 sk_buff 内存和清理 RingBuffer 内存。

最后,当收到这个 TCP 报文的 ACK 应答时,传输层就会释放原始的 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。


版权声明:本文为qq_42435122原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。