网络层与传输层概述
网络层:
- 抽象概念:网络层是基于 IP 的抽象概念,与数据链路层用 MAC 地址标记设备不同。MAC 地址是一种具体化的概念,绑定于所在的物理网络,而 IP 地址可以是固定的,也可以通过路由动态变化。
- 功能:所有“网络”的“网”是基于 IP 的抽象概念,而链路层的“路”是基于 MAC 的具体化概念。
传输层:
- 协议决定内容:传输层与物理信号的形式(光信号、电信号、无线信号)或目的地无关,传输层的协议决定了传输的内容是可靠的还是不可靠的。例如:
- 不可靠传输协议:适用于允许丢帧和数据丢失的流媒体传输。
- 可靠传输协议:适用于需要保密、稳定且不允许数据损坏或丢失的场景,并能控制传输的速度和质量。
数据链路层的作用与网卡驱动
数据链路层的命名
数据链路层之所以称为“链路层”,是因为它负责在物理链路上传输数据。链路指网络中相邻节点之间的物理连接(例如两台计算机或交换机)。
数据链路层的主要作用
帧的封装和拆解:
- 把网络层的数据打包成帧(Frame)。
- 在接收端解包帧,提取网络层数据。
差错检测与纠正:
- 使用校验和机制(如 CRC)检测传输过程中的错误。
- 部分情况下还能纠正错误。
流量控制与重传:
- 控制数据流速,防止发送过快导致接收端无法处理。
- 在数据帧丢失时请求重传。
MAC 地址管理:
- 确保数据在局域网内正确发送到目标设备。
数据链路层与网卡驱动的关系
- 数据链路层的职责:定义如何在物理链路上传输帧,并确保数据传输的可靠性。
- 网卡驱动的职责:
- 是数据链路层的一部分。
- 负责从网卡接收数据并传递给网络层。
- 与操作系统协作完成数据链路层功能。
数据链路层与网络层的关系
- 网络层的职责:负责逻辑寻址和跨网络的数据路由。
- 网络层的工作方式:
- 接收来自链路层的帧,解封装出 IP 数据包。
- 基于 IP 地址和路由信息,将数据传递到目的地。
TCP/IP 协议栈
tcp组包时 校验和 计算 -- 按照协议中指出,校验和本身在校验时 作为0计算。
校验和前面 还包含了 伪包头 包含了IP地址,是为了防止路由错IP
主要组成部分
- 链路层(Link Layer):对应 OSI 模型中的数据链路层。
- 网络层(Internet Layer):主要协议是 IP,负责跨网络的数据路由。
- 传输层(Transport Layer):如 TCP 和 UDP,提供端到端的数据传输。
- 应用层(Application Layer):处理应用数据和服务,如 HTTP、FTP。
数据包的传递流程
- 链路层负责在物理网络中传输数据帧。
- 网络层通过路由实现数据的跨网络传递。
- 传输层提供可靠或不可靠的数据传输服务。
网卡驱动与 sk_buff
结构体
sk_buff
的作用
- 是 Linux 内核中描述网络数据包的重要数据结构。
- 用于存储和管理网络协议栈的所有数据包。
典型的数据包接收流程
- 网卡驱动接收数据:
- 网卡驱动接收到数据包后,分配一个
sk_buff
。 - 将数据存储到
sk_buff
的缓冲区中。
- 网卡驱动接收到数据包后,分配一个
- 传递给协议栈:
- 通过
netif_rx()
等函数将sk_buff
传递给网络层。
- 通过
- 网络层处理:
- 解封装数据,提取 IP 包进行进一步处理。
sk_buff
的主要字段
data
:指向数据部分。len
:数据长度。protocol
:上层协议类型。dev
:关联的网络设备。- 头部信息指针:
mac_header
、network_header
、transport_header
。
sk_buff
示例
struct sk_buff *skb = netdev_alloc_skb(dev, len);
if (!skb) {
return -ENOMEM;
}
memcpy(skb_put(skb, len), data, len);
skb->protocol = eth_type_trans(skb, dev);
netif_rx(skb);
传输层与 TCB 结构体
TCB 的作用
- **传输控制块(TCB, Transmission Control Block)**用于管理和维护 TCP 连接。
- 在 Linux 内核中,TCB 主要由
struct tcp_sock
表示。
tcp_sock
定义位置
- 定义于
include/net/tcp.h
。
tcp_sock
的主要字段
snd_nxt
:发送窗口的下一个序列号。rcv_nxt
:接收窗口的下一个序列号。snd_una
:未被确认的序列号。sk_receive_queue
:接收队列。sk_write_queue
:发送队列。
tcp_sock
的连接生命周期
- 初始化:三次握手时分配并初始化。
- 状态更新:更新发送和接收窗口的序列号。
- 关闭连接:释放
tcp_sock
,完成连接关闭。
传输层的数据流向
- 发送方向:
- 数据通过
send()
进入传输层,存储到发送缓冲区。 - 在合适时机发送到网络。
- 数据通过
- 接收方向:
- 数据通过网卡驱动传递到
sk_buff
,存储到接收缓冲区。 - 应用层通过
recv()
获取数据。
- 数据通过网卡驱动传递到
tcp_sock
示例
struct tcp_sock {
__u32 snd_nxt;
__u32 rcv_nxt;
__u32 snd_una;
struct sk_buff_head write_queue;
struct sk_buff_head receive_queue;
// 其他状态变量
};
总结
- 数据链路层处理物理链路上的数据传输,网卡驱动是其一部分。
- 网络层负责跨网络的数据路由,是 TCP/IP 协议栈的重要组成。
sk_buff
是 Linux 内核中描述网络数据包的核心数据结构。tcp_sock
用于管理 TCP 连接,是传输层的重要组件。
传输控制块(TCB)简介
在 Linux 网络协议栈中,传输控制块(TCB, Transmission Control Block) 是用于管理和维护传输层连接的核心数据结构。对于 TCP 协议来说,TCB 主要由 struct tcp_sock
结构体表示,它定义了 TCP 连接的状态和相关的控制信息。
1. struct tcp_sock
的定义位置
tcp_sock
结构体定义在内核代码的 include/net/tcp.h
文件中,是 Linux 内核对 TCP 连接进行管理的主要结构体。
2. tcp_sock
的作用
- TCP 连接状态信息:保存 TCP 连接的四元组(源 IP、目的 IP、源端口、目的端口)和状态(如 ESTABLISHED, SYN_SENT 等)。
- 窗口大小与重传信息:用于管理 TCP 滑动窗口大小、重传计时器和拥塞控制。
- 发送和接收缓冲区:包括发送队列和接收队列,分别存储未发送的数据和已接收但未处理的数据。
- 序列号管理:跟踪和管理 TCP 的序列号和确认号,以保证数据包的顺序和可靠性。
3. tcp_sock
的主要字段
以下列举了 tcp_sock
中的一些关键字段及其作用:
字段名 | 作用 |
---|---|
rcv_nxt |
接收窗口的下一个序列号 |
snd_nxt |
发送窗口的下一个序列号 |
snd_una |
第一个未被确认的字节的序列号 |
copied_seq |
接收队列中已被应用程序读取的字节序列号 |
write_seq |
发送队列中已被写入但未发送的下一个字节序列号 |
sk_receive_queue |
已接收但未处理的数据包队列 |
sk_write_queue |
待发送的数据包队列 |
4. tcp_sock
的连接生命周期
1. 初始化
当一个新的 TCP 连接建立时,内核会为该连接分配并初始化一个 tcp_sock
结构体,记录四元组并设置初始状态(如 SYN_SENT
或 SYN_RECV
)。
2. 状态更新
随着 TCP 三次握手及后续通信的进行,tcp_sock
的状态和字段不断更新。例如:
- 数据发送时,更新发送窗口中的
snd_nxt
和snd_una
。 - 数据接收时,更新接收窗口中的
rcv_nxt
。
3. 关闭连接
TCP 连接关闭时,tcp_sock
状态会更新为 CLOSE_WAIT
或 FIN_WAIT
,最终释放内存。
5. 从哪里到哪里
1. 发送方向
当应用层调用 send()
时,数据经由套接字接口进入传输层,TCP 层通过 tcp_sendmsg()
处理这些数据,将其存入 tcp_sock
的发送缓冲区,待网卡驱动发送到网络中。
2. 接收方向
当网卡驱动接收到 TCP 数据包后,数据会通过 sk_buff
传递到 TCP 层。TCP 根据数据包的序列号将其存入 tcp_sock
的接收缓冲区,供应用层调用 recv()
获取。
6. 简单示例:tcp_sock
部分定义
以下是 tcp_sock
的简化定义:
struct tcp_sock {
__u32 snd_nxt; // 发送窗口的下一个序列号
__u32 rcv_nxt; // 接收窗口的下一个序列号
__u32 snd_una; // 第一个未被确认的字节的序列号
struct sk_buff_head write_queue; // 待发送的 skb 队列
struct sk_buff_head receive_queue; // 已接收但未处理的 skb 队列
// 其他用于管理 TCP 连接的状态变量
};
总结
- TCB(传输控制块) 在 Linux 中主要由
struct tcp_sock
表示,是 TCP 协议管理的核心数据结构。 - 它的定义位于
include/net/tcp.h
文件中,保存了 TCP 协议中的关键信息,包括连接状态、序列号、窗口大小、发送与接收队列等。