当前位置: 首页 > backend >正文

TCP/IP函数——sendmsg

sendmsg() 是 POSIX 标准中一个高级套接字发送函数,属于系统调用(由操作系统内核实现),定义在 <sys/socket.h> 头文件中。它的核心特点是支持复杂消息结构,不仅能发送常规数据,还能附加控制信息(如辅助数据、IP 选项等),适用于 TCP、UDP 等多种协议,功能比 send()/sendto() 更灵活。

一、函数原型

#include <sys/socket.h>ssize_t sendmsg(int sockfd, const struct msghdr *msg, int flags);

二、参数详解

1. sockfd(套接字描述符)

类型:int
作用:已创建的套接字描述符(如通过 socket() 创建的 TCP 或 UDP 套接字)。
要求:若为 UDP 等无连接协议,需在 msg 中指定目标地址;若为 TCP 等已连接协议(通过 connect() 绑定),可省略地址。

2. msg(消息结构,核心参数)

类型:const struct msghdr *
作用:指向 struct msghdr 结构体,该结构体封装了发送的数据、目标地址、控制信息等所有与消息相关的内容。

struct msghdr 结构体定义如下(不同系统可能略有差异,以 Linux 为例):

struct msghdr {void         *msg_name;       // 目标地址(可选,仅无连接协议需要)socklen_t     msg_namelen;    // 目标地址长度struct iovec *msg_iov;        // 数据缓冲区数组(常规数据)size_t        msg_iovlen;     // 数据缓冲区数量void         *msg_control;    // 控制信息缓冲区(辅助数据)size_t        msg_controllen; // 控制信息缓冲区大小int           msg_flags;      // 接收时的标志(发送时忽略)
};

各字段详解:

在这里插入图片描述

辅助结构:struct iovec(数据缓冲区)

-msg_iov 指向的 struct iovec 数组用于定义常规数据的缓冲区,结构如下:

struct iovec {void  *iov_base;  // 缓冲区起始地址(数据存放的内存位置)size_t iov_len;   // 缓冲区长度(要发送的字节数)
};
  • 作用:支持 “分散发送”—— 将多个不连续的缓冲区数据合并成一个消息发送(无需先手动拼接)。

辅助结构:控制信息(cmsghdr)

msg_control 指向的控制信息缓冲区用于存储辅助数据,格式由 struct cmsghdr 定义:

struct cmsghdr {size_t cmsg_len;   // 控制信息的总长度(含头部和数据)int    cmsg_level; // 协议级别(如 SOL_SOCKET、IPPROTO_IP)int    cmsg_type;  // 控制信息类型(如 SCM_RIGHTS 表示传递文件描述符)// 数据部分(紧跟在结构体后,需通过宏访问)
};
  • 常见用途:
    通过 Unix 域套接字传递文件描述符(SCM_RIGHTS)。
    设置 IP 选项(如 IP_TTL 控制生存时间)。
    传递网络接口索引(绑定特定网卡发送)。

3. flags(发送标志)

  • 类型:int
  • 作用:控制发送行为,与 send()/sendto() 的 flags 参数相同,可组合使用(通过按位或 |)。
  • 常见取值:
    0:默认行为。
    MSG_DONTROUTE:不经过路由表,仅在本地网络发送。
    MSG_DONTWAIT:非阻塞发送(若套接字为阻塞模式,临时转为非阻塞)。
    MSG_NOSIGNAL:发送 TCP 数据时,若对方已关闭连接,不产生 SIGPIPE 信号。
    三、返回值
    成功:返回实际发送的字节数(仅计算 msg_iov 中的常规数据,不包含控制信息)。
    失败:返回 -1,并设置 errno 表示错误原因(如 EBADF 表示套接字无效,EINVAL 表示参数错误)。

四、使用场景与示例

sendmsg() 因支持控制信息和分散发送,适合以下场景:

1.传递辅助数据(如文件描述符、IP 选项)。
2.发送分散在多个缓冲区的数据(避免手动拼接)。

4.1 用 sendmsg() 实现 UDP 数据发送,功能等同于 sendto():

#include <stdio.h>
#include <sys/socket.h>
http://www.xdnf.cn/news/20179.html

相关文章:

  • 怎么获取Nano Banana的APK Key?
  • Dify基础应用
  • 1分钟了解等保测评流程
  • Kubernetes 全景指南:从核心概念到云原生未来
  • BYOFF(自定义格式函数)(79)
  • 如何安全地删除与重建 Elasticsearch 的 .watches 索引
  • 人工智能之数学基础:逻辑回归算法的概率密度函数与分布函数
  • 3个维度打造差异化内容,告别运营焦虑
  • 老年公寓管理系统设计与实现(代码+数据库+LW)
  • 从零开始学大模型之动手搭建大模型
  • LLM与数据工程的融合:衡石Data Agent的语义层与Agent框架设计
  • 自制扫地机器人 (五) Arduino 手机远程启停设计 —— 东方仙盟
  • 基于C#实现USB转串口读取扫描枪数据
  • 从重金挖角OpenAI/谷歌到招聘急刹车:Meta MSL主要人员梳理,半数华人+75%博士成主力
  • 沙堆状态的可视化图和雪崩分布
  • Day21_【机器学习—决策树(3)—剪枝】
  • java面试中经常会问到的zookeeper问题有哪些(基础版)
  • Vue3 频率范围输入失焦自动校验实现
  • Windows 11主机Ubuntu 24.04虚机共享目录权限问题
  • MySQL问题4
  • 阿里云服务器配置ssl-docker nginx
  • 企业数字安全双保险:终端安全与数据防泄漏如何构筑全方位防护体系
  • React Hooks useContext
  • AI API Tester体验:API测试工具如何高效生成接口测试用例、覆盖异常场景?
  • 【建图+dsf/最长上升子序列dp】【记录最优解路径】P2196 [NOIP 1996 提高组] 挖地雷
  • C++ 音视频开发常见面试题及答案汇总
  • 【软考架构】V模型、W模型、增量模型和螺旋模型
  • Oracle 10g → Oracle 19c 升级后问题解决方案(Pro*C 项目)
  • Redis 内存管理机制:深度解析与性能优化实践
  • 阿里云国际代理:阿里云的云数据库是什么?