struct msghdr
2026/4/24 14:12:40 网站建设 项目流程

1 是什么?

struct msghdr 在 C 语言网络编程 是套接字消息通信的核心数据结构 是 sendmsg 和 recvmsg 这两个高级套接字 I/O 函数的关键参数。 与功能相对简单的 send 和 recv 相比, msghdr 最大的优势在于支持聚集/分散 I/O 和控制信息(辅助数据) 的传递, 例如在进程间传递文件描述符

2 定义

#include<sys/socket.h>structmsghdr{void*msg_name;// 指向套接字地址结构(如 struct sockaddr)socklen_tmsg_namelen;// msg_name 的长度structiovec*msg_iov;// 指向 iovec 数组(分散/聚集 I/O)size_tmsg_iovlen;// msg_iov 数组的元素个数void*msg_control;// 指向辅助数据/控制信息缓冲区socklen_tmsg_controllen;// msg_control 缓冲区的长度intmsg_flags;// 消息标志(输入控制行为,输出返回状态)};
`struct msghdr` 成员解析 `struct msghdr` 通过组合多个成员来实现其强大功能, 其主要成员可以分为四组: `msg_name` 和 `msg_namelen`: 用于指定或获取套接字地址。 `msg_name` 是一个指向 `sockaddr` 结构体的指针,`msg_namelen` 是该地址的长度。 在 `sendmsg` 中指定目标地址,在 `recvmsg` 中则可获取数据来源地址。 对于已连接的面向连接套接字(如 TCP),这些成员通常被忽略。 `msg_iov` 和 `msg_iovlen`: 实现聚集/分散 I/O。 `msg_iov` 指向一个 `struct iovec` 结构体数组,`msg_iovlen` 是数组的长度。 这允许你将数据从多个不连续的内存缓冲区发送出去,或接收到多个缓冲区中。 `msg_control` 和 `msg_controllen`: 用于处理辅助数据。 `msg_control` 指向辅助数据缓冲区,`msg_controllen` 是缓冲区大小。 辅助数据由一系列 `cmsghdr` 结构体及其附属数据构成。 `msg_flags`: 仅用于 `recvmsg` 接收特定的标志位,如 `MSG_EOR` (记录结尾)、`MSG_OOB` (带外数据) 等。

3 关联数据结构

关键附加结构 要完整理解和使用 `msghdr`,还需要了解以下几个紧密关联的结构体和宏函数: `struct iovec`: 用于 `msg_iov` 成员,定义在 `<sys/uio.h>` 中, 包含 `void *iov_base` (缓冲区地址) 和 `size_t iov_len` (长度)。 `struct cmsghdr` 与辅助数据: 辅助数据由一系列 `struct cmsghdr` 构成,用于传递控制信息, 如 Unix 域套接字中的文件描述符或 IP 数据包信息等。 操作辅助数据需使用专用的宏函数,而非直接访问内存。 辅助数据专用宏函数: `CMSG_FIRSTHDR(msghdr)`: 获取 msghdr 中第一个 `cmsghdr` 结构。 `CMSG_NXTHDR(msghdr, cmsg)`: 获取下一个 `cmsghdr` 结构。 `CMSG_DATA(cmsg)`: 通过 `cmsghdr` 获取其附属数据的地址。

4 struct cmsghdr 与 struct msghdr

struct cmsghdrstruct msghdr是 包含与被包含 的关系。

简单来说:
struct msghdr是一次消息通信的“总信封”,
struct cmsghdr是信封中msg_control字段所指向的“辅助数据区”里的单个控制项头部。

struct cmsghdr用于描述 单个辅助数据(Ancillary/Control Data)


`struct cmsghdr` 与 `struct msghdr` 的具体联系
msghdr字段cmsghdr的关系
msg_control指向一块原始字节缓冲区,该缓冲区内按顺序存放一个或多个struct cmsghdr及其附属数据。
msg_controllen该缓冲区的总字节数。发送前需计算好大小,接收时由内核填入实际接收的控制数据长度。
逻辑关系msghdr提供“容器”,cmsghdr是容器内的“条目”。一个msg_control缓冲区可包含多个cmsghdr(如同时传递 FD 和凭证)。

内存布局示意

msg_control 缓冲区: [ cmsghdr1 ][ 数据1 ][ 对齐填充 ][ cmsghdr2 ][ 数据2 ]...

为什么不能直接操作指针?→ 必须使用 `CMSG_*` 宏族 由于 `cmsghdr` 之间存在**内存对齐填充**,直接 `ptr + sizeof(struct cmsghdr)` 会越界或读错数据。 POSIX 规定必须使用以下宏:
作用
CMSG_SPACE(len)计算存放长度为len的数据所需的总空间(含头部+数据+尾部对齐填充)。用于分配msg_control缓冲区。
CMSG_LEN(len)计算应写入cmsg_len的值(含头部+数据,不含尾部填充)。
CMSG_DATA(cmsg)返回指向该控制项实际数据区的指针。
CMSG_FIRSTHDR(msgh)获取msg_control缓冲区中的第一个cmsghdr
CMSG_NXTHDR(msgh, cmsg)获取下一个cmsghdr;若已无后续项则返回NULL

常见cmsg_level/cmsg_type组合

层级 (cmsg_level)类型 (cmsg_type)传递内容
SOL_SOCKETSCM_RIGHTS文件描述符(Unix Domain Socket)
SOL_SOCKETSCM_CREDENTIALS进程 UID/GID/PID 凭证
IPPROTO_IPIP_PKTINFO/IP_TTL数据报源接口、TTL 等
IPPROTO_IPV6IPV6_PKTINFOIPv6 地址/接口信息
SOL_SOCKETSCM_TIMESTAMPING硬件/软件时间戳

总结

维度struct msghdrstruct cmsghdr
定位消息通信的总控制块辅助数据区的单个条目头部
关联字段msg_control,msg_controllen存在于msg_control指向的缓冲区中
操作方式直接赋值地址/长度必须通过CMSG_*安全访问
典型用途统一封装地址、数据块、控制信息、标志位传递 FD、凭证、IP 元数据、时间戳等内核附加信息

msghdr是消息的“信封”和“载体”,
cmsghdr是信封内用来携带“控制信息”的结构化便签

没有msghdr提供的辅助数据缓冲区,cmsghdr就无处安放;
没有cmsghdr对控制信息的标准化封装,msghdr就无法传递文件描述符、IP 选项等高级内容。

msghdr是外壳,cmsghdr是内件;
msg_control是字节流,CMSG_*是解析器

在编写高性能网络服务、容器进程间通信或底层抓包工具时,
这套机制是传递元数据和特殊资源的唯一标准途径。


需要专业的网站建设服务?

联系我们获取免费的网站建设咨询和方案报价,让我们帮助您实现业务目标

立即咨询