Skip to content

NET_DataPacket

SweerItTer edited this page Feb 21, 2026 · 1 revision

DataPacket

概述

DataPacket 是数据包类型,支持多种数据传输方式,包括普通文本、DMA-BUF 零拷贝和裸文件描述符。

类型定义

struct DataPacket {
    enum class PacketType : uint8_t {
        TEXT,           // 普通文本数据
        DMABUF_FD,      // DMA-BUF文件描述符
        RAW_FD          // 裸文件描述符
    };

    PacketType type;
    std::string textData;           // type == TEXT时使用
    int dmaFd{-1};                  // type == DMABUF_FD时使用
    DmaBufferPtr dmabufPtr{nullptr}; // type == DMABUF_FD时使用(持有所有权)
    int rawFd{-1};                  // type == RAW_FD时使用
};

数据类型

1. TEXT (文本数据)

描述: 普通文本数据,使用 send() 发送。

适用场景:

  • 命令响应
  • 配置信息
  • 状态查询
  • 日志输出

特点:

  • 简单易用
  • 自动序列化
  • 支持任意字符串

2. DMABUF_FD (DMA-BUF 文件描述符)

描述: DMA-BUF 文件描述符,使用 sendmsg() + SCM_RIGHTS 发送,实现零拷贝传输。

适用场景:

  • 视频帧传输
  • 图像数据传输
  • 大数据块传输
  • 多媒体应用

特点:

  • 零拷贝,性能高
  • 需要 DRM 支持
  • 自动管理生命周期
  • 跨进程共享

3. RAW_FD (裸文件描述符)

描述: 裸文件描述符,使用 sendmsg() + SCM_RIGHTS 发送。

适用场景:

  • 共享文件描述符
  • 管道传输
  • Socket 转发
  • 资源共享

特点:

  • 灵活通用
  • 支持任意 FD
  • 手动管理生命周期

工厂方法

createText()

签名:

static DataPacket createText(const std::string& data)

描述: 创建文本数据包。

参数:

  • data: 文本数据

返回值: DataPacket 对象

示例:

DataPacket pkt = DataPacket::createText("Hello World");
server.sendToClient(clientId, pkt);

使用场景:

  • 命令响应
  • 状态信息
  • 配置数据
  • 普通消息

createDmaBuf()

签名:

static DataPacket createDmaBuf(DmaBufferPtr dmabuf)

描述: 创建 DMA-BUF 数据包(零拷贝)。

参数:

  • dmabuf: DMA-BUF 指针

返回值: DataPacket 对象

示例:

// 创建 DMA-BUF
DmaBufferPtr dmabuf = DmaBuffer::create(1920, 1080, DRM_FORMAT_ARGB8888);

// 填充数据
memset(dmabuf->map(), 0xFF, dmabuf->size());

// 创建数据包
DataPacket pkt = DataPacket::createDmaBuf(dmabuf);
server.sendToClient(clientId, pkt);

使用场景:

  • 视频帧传输
  • 图像数据传输
  • 大数据块传输
  • 多媒体应用

注意事项:

  • 需要 DRM 支持
  • 自动管理生命周期
  • 零拷贝传输,性能高

createRawFd()

签名:

static DataPacket createRawFd(int fd)

描述: 创建裸文件描述符数据包。

参数:

  • fd: 文件描述符

返回值: DataPacket 对象

示例:

// 打开文件
int fd = open("/path/to/file.txt", O_RDONLY);

// 创建数据包
DataPacket pkt = DataPacket::createRawFd(fd);
server.sendToClient(clientId, pkt);

// 注意:fd 会在发送后被关闭

使用场景:

  • 共享文件描述符
  • 管道传输
  • Socket 转发
  • 资源共享

注意事项:

  • FD 会在发送后被关闭
  • 确保接收端正确处理
  • 手动管理生命周期

使用示例

文本数据发送

// 命令响应
DataPacket pkt = DataPacket::createText("OK File received");
server.sendToClient(clientId, pkt);

// 状态信息
DataPacket status = DataPacket::createText("Server is running");
server.broadcast(status);

// 配置数据
DataPacket config = DataPacket::createText("PORT=8080,MAX_CLIENTS=64");
server.sendToClient(clientId, config);

DMA-BUF 零拷贝传输

// 创建 DMA-BUF
DmaBufferPtr dmabuf = DmaBuffer::create(1920, 1080, DRM_FORMAT_ARGB8888);

// 填充数据(视频帧)
uint32_t* pixels = static_cast<uint32_t*>(dmabuf->map());
for (int i = 0; i < 1920 * 1080; ++i) {
    pixels[i] = 0xFF0000;  // 红色
}

// 创建数据包
DataPacket pkt = DataPacket::createDmaBuf(dmabuf);

// 发送给客户端(零拷贝)
server.sendToClient(clientId, pkt);

文件描述符传输

// 打开文件
int fd = open("/path/to/large_file.dat", O_RDONLY);
if (fd < 0) {
    // 发送错误
    server.sendToClient(clientId, DataPacket::createText("ERROR Cannot open file"));
    return;
}

// 创建数据包
DataPacket pkt = DataPacket::createRawFd(fd);

// 发送给客户端
server.sendToClient(clientId, pkt);

// 注意:fd 会在发送后被自动关闭

广播示例

// 广播文本消息
DataPacket broadcastMsg = DataPacket::createText("Server will restart in 5 minutes");
size_t sent = server.broadcast(broadcastMsg);
std::cout << "Broadcast to " << sent << " clients" << std::endl;

// 广播视频帧(多个客户端)
DmaBufferPtr frame = captureVideoFrame();
DataPacket pkt = DataPacket::createDmaBuf(frame);
size_t sent = server.broadcast(pkt);

内部实现

文本数据发送

创建 DataPacket (type = TEXT)
  ├─ 设置 textData
  └─ 发送队列
      └─ send()
          ├─ 序列化
          └─ 发送到 socket

DMA-BUF 零拷贝传输

创建 DataPacket (type = DMABUF_FD)
  ├─ 保存 dmabufPtr (持有所有权)
  └─ 发送队列
      └─ sendmsg() + SCM_RIGHTS
          ├─ 提取 fd (dmabuf->fd())
          ├─ 构建 msghdr
          └─ 发送(零拷贝)

裸 FD 传输

创建 DataPacket (type = RAW_FD)
  ├─ 保存 rawFd
  └─ 发送队列
      └─ sendmsg() + SCM_RIGHTS
          ├─ 构建 msghdr
          └─ 发送

性能对比

类型 拷贝次数 性能 适用场景
TEXT 2次 中等 命令响应、配置
DMABUF_FD 0次 最高 视频帧、大数据
RAW_FD 0次 文件共享、管道

拷贝次数说明:

  • TEXT: 内存 → 内核 → 网络(2次)
  • DMABUF_FD: 直接传输(0次)
  • RAW_FD: 直接传输(0次)

错误处理

发送失败

DataPacket pkt = DataPacket::createText("Hello");
if (!server.sendToClient(clientId, pkt)) {
    // 发送失败
    std::cerr << "Send failed" << std::endl;
}

DMA-BUF 创建失败

DmaBufferPtr dmabuf = DmaBuffer::create(1920, 1080, DRM_FORMAT_ARGB8888);
if (!dmabuf) {
    // DMA-BUF 创建失败
    server.sendToClient(clientId, DataPacket::createText("ERROR Cannot create DMA-BUF"));
    return;
}

FD 无效

int fd = open("/path/to/file.txt", O_RDONLY);
if (fd < 0) {
    // FD 无效
    server.sendToClient(clientId, DataPacket::createText("ERROR Cannot open file"));
    return;
}

最佳实践

  1. 选择合适的类型:

    • 普通数据使用 TEXT
    • 视频/大块数据使用 DMABUF_FD
    • 文件共享使用 RAW_FD
  2. 生命周期管理:

    • DMABUF_FD: 自动管理,无需手动释放
    • RAW_FD: 发送后自动关闭
    • TEXT: 无生命周期问题
  3. 性能优化:

    • 大数据使用零拷贝
    • 批量发送使用队列
    • 避免频繁创建/销毁
  4. 错误处理:

    • 检查发送结果
    • 验证 FD 有效性
    • 捕获异常

相关类

参考资料

主页

API 文档

DMA 模块

DRM 模块

NET 模块

V4L2 模块

V4L2Param 模块

RGA 模块

MPP 模块

Sys 模块

Mouse 模块

Utils 模块

Clone this wiki locally