网络套接字iovec API有什么用

文章探讨了如何利用iovec接口在面向连接的工作模式下节省系统调用和数据拷贝,特别是在需要添加报文头的场景中,通过scatter/gather操作避免了用户空间到内核空间的数据拷贝,从而提高了网络通信的效率。

结论先行

  • 对于面向连接的工作模式,可以节省系统调用API的次数
  • 可以让报文缓冲区分配和管理更具弹性
    • 适合的场景将节省一次用户空间内、不必要的拷贝

前言

很久以前就知道网络Socket套接字API存在iovec接口,曾以为它能够实现零拷贝,但是,简单分析后,发现iovec指向的也是用户空间的地址,所以,认为它没什么太大价值,不能够实现用户空间到内核空间的零拷贝,就没有继续深入学习研究下去。

直到最近研究recvmmsg接口,以及伴随一直思考的的性能优化任务,突然对iovec产生了理解的电火花,用网络套接字iovec类接口,可以对适用的场景节省一次不必要的数据拷贝工作!

下面列举一个比较容易理解的例子 😃

不知道IOVEC接口前

简而言之,例子就是组件API对上层提供发送网络报文接口,但对于接口参数传递的报文数据,又必须在入参数据前加上扩展头后,才能发送出去,而且不得不做!

  • 不使用iovec
    • 组件API实现将不得不通过构造一个完整的报文数据区,构造新包头,拷贝入参报文数据后,将此新报文数据区发送出去
    • 与上层API存在工作协议,在入参报文数据区前能够提供前缀的工作空间,以便于组件API实现可以在不拷贝入参报文缓冲区的情况下,添加了新包头后进行发送

但是,在知道了iovec类接口后,就不需要这么复杂了!!!

scatter/gather操作

  • 流模式,按iovec次序分散和收集
  • 报文模式,将一次收发dgram,按iovec次序分散和收集

以前笔记积累过网络操作报文缓冲区预留前后缀空间的最佳实践

具体例子

反例

extern struct T_GTPUHeader;

int sendMessageToPeer(..., const char* data, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen)
{
  unsigned char abEncodeBuf[MAX_PKG];
  
  struct T_GTPUHeader*  ptGTPUHeader = (T_GTPUHeader*)abEncodeBuf;
  // Use the input paras or some global info
  fillGTPUHeader(ptGTPUHeader, ...);
  
  // 多一次用户空间内的拷贝
  memcpy(abEncodeBuf + sizeof(struct T_GTPUHeader), data, len);
  
  // get sockfd by some mean
  return sendto(sockfd, abEncodeBuf, sizeof(struct T_GTPUHeader) + len, flags, dest_addr, addrlen);
}

正例

extern struct T_GTPUHeader;

int sendMessageToPeer_iovec(..., const char* data, size_t len, int flags, struct sockaddr *dest_addr, socklen_t addrlen)
{
  
  struct T_GTPUHeader  tGTPUHeader = {};
  // Use the input paras or some global info
  fillGTPUHeader(&tGTPUHeader, ...);

  // Use iovec api
  struct iovec vec[2];
  vec[0].iov_base = &tGTPUHeader;
  vec[0].iov_len  = sizeof(tGTPUHeader);
  vec[1].iov_base = data;
  vec[1].iov_len  = len;
  
  struct msghdr  msghdr = {};
  msghdr.msg_name    = dest_addr;
  msghdr.msg_namelen = addrlen;
  msghdr.msg_iov     = &vec;        /* scatter/gather array */
  msghdr.msg_iovlen  = sizeof(vec)/sizeof(vec[0]);  /* # elements in msg_iov */

  // get sockfd by some mean
  return sendmsg(sockfd, &msghdr, flags);
}

图解

发送

节省一次内存拷贝

接收

更自由的内存管理

iovec可支持更自由的内存管理

参考

<think>我们正在讨论C++网络库的功能和应用场景。根据引用[1]的内容,我们可以了解到不同网络库的特点和适用场景。但用户的问题更关注于C++网络库的通用功能和典型应用场景,因此我们需要从更一般的角度来回答。 C++网络库的核心功能是提供网络通信能力,包括但不限于: 1. 创建和管理网络连接(TCP/UDP) 2. 实现高效的I/O多路复用(如Reactor模式) 3. 提供异步/同步编程接口 4. 支持协议解析(如HTTP、WebSocket等) 5. 提供安全通信(如SSL/TLS) 应用场景: - 高性能服务器:游戏服务器、金融交易系统等需要高并发的场景 - 分布式系统:微服务之间的通信 - 实时通信:即时通讯、视频直播 - 物联网:设备与服务器之间的通信 - Web服务:HTTP服务器、API服务 根据引用[1],我们可以进一步结合主流网络库的特点来说明: - muduo和Sogou Workflow:适合需要极致性能的Linux服务器,如搜索引擎、高性能代理等。 - Boost.Asio和libuv:适合跨平台应用,如桌面应用的后台服务、跨平台游戏服务器。 - libevent和POCO:适合快速开发轻量级服务,如企业内部系统、小型Web服务。 下面我们详细展开回答。</think>### C++ 网络库的核心功能与应用场景 #### 一、核心功能 1. **网络通信基础** - TCP/UDP 套接字封装:提供跨平台的套接字创建、连接和管理功能 - 异步 I/O 操作:基于事件驱动模型(如 Reactor/Proactor)实现非阻塞通信 ```cpp // Boost.Asio 异步连接示例 socket.async_connect(endpoint, [](const error_code& ec) { if (!ec) std::cout << "Connected!\n"; }); ``` 2. **协议支持** | 协议类型 | 典型实现库 | 应用案例 | |----------------|---------------------|------------------------------| | HTTP/HTTPS | libcurl, Boost.Beast | Web API 服务 | | WebSocket | libwebsockets | 实时聊天、股票行情推送 | | RPC | gRPC, Thrift | 微服务通信 | | 自定义协议 | 原始套接字封装 | 游戏通信协议、物联网协议 | 3. **高性能并发模型** - Reactor 模式:单线程事件循环(如 libevent) - Proactor 模式:异步 I/O 完成端口(Windows IOCP) - 混合模式:多线程 Reactor(如 muduo 的 `EventLoopThreadPool`) 4. **连接管理** - 连接池:复用 TCP 连接减少握手开销 - 负载均衡:自动分配请求到多个后端服务 - 故障转移:心跳检测 + 自动重连机制 5. **安全通信** - SSL/TLS 集成:支持加密通信(OpenSSL 集成) - 证书验证:双向认证保障通信安全 #### 二、典型应用场景 1. **高性能服务器开发** - 使用 muduo/Sogou Workflow 构建百万级并发服务[^1] - 案例:网易游戏服务器、搜狗搜索引擎后端 2. **分布式系统通信** - 微服务间 RPC 调用(gRPC) - 服务发现与注册中心交互 3. **实时数据传输** ```mermaid graph LR A[客户端] -->|WebSocket| B(消息中间件) B --> C[行情服务器] B --> D[聊天服务器] ``` 典型场景:金融行情推送(每秒万级消息)、在线协作工具 4. **物联网(IoT)平台** - 设备接入层:处理海量设备连接(libuv 的跨平台优势) - 边缘计算:轻量级协议解析(COAP/MQTT) 5. **云原生基础设施** - Service Mesh 数据平面(Envoy 的 C++核心) - API 网关:请求路由、限流、认证 #### 三、选型建议 | 需求场景 | 推荐库 | 关键优势 | |-------------------------|-----------------------|------------------------------| | Linux 极致性能 | muduo / Sogou Workflow | 针对 epoll 深度优化[^1] | | 跨平台支持 | Boost.Asio / libuv | Windows/Linux/macOS 全兼容 | | 快速开发轻量服务 | libevent / POCO | 简洁 API,丰富工具集 | | 企业级协议支持 | gRPC / Thrift | 内置 PB/Thrift 序列化 | > **性能数据参考**:在 24 核 Linux 服务器上,muduo 可处理 120 万 QPS 的短连接请求,内存占用仅为 Java Netty 的 1/3[^1]。 #### 四、开发实践要点 1. **连接生命周期管理** 使用 `shared_ptr` 管理会话对象,避免回调中访问已释放资源: ```cpp auto session = std::make_shared<Session>(socket); session->start(); // 引用计数保障安全 ``` 2. **缓冲区设计** 采用分散-聚集 I/O(`readv`/`writev`)减少内存拷贝: ```cpp struct iovec iov[2]; iov[0].iov_base = header; iov[1].iov_base = body; ``` 3. **协议解析优化** - 零拷贝解析:直接操作网络缓冲区 - 状态机实现:高效处理流式协议(如 HTTP chunk) 4. **资源限制策略** ```cpp // 连接数限制示例 if (active_connections.load() >= MAX_CONN) { socket.close(); // 拒绝新连接 } ```
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值