UDP通信库 v1.0.0

C++17 跨平台 多线程 最后更新: 2026-03-17

一个功能强大、易于使用的C++ UDP通信库,支持多线程、消息过滤、统计信息等功能。

📖 概述

UDP通信库是一个现代化的C++网络编程库,提供了完整的UDP通信解决方案。它封装了底层的socket操作,提供了高级的API接口,使开发者能够快速构建可靠的UDP通信应用。

💡 设计理念: 简单易用、功能强大、性能优异、可扩展。

核心组件

✨ 特性

📦 完整协议

标准化的消息格式,支持多种数据类型,易于扩展

⚡ 高性能

零拷贝设计,异步处理,支持高并发场景

🔄 多线程支持

独立的接收线程,消息队列,避免阻塞

🎯 消息过滤

按消息类型过滤,自定义回调处理

📊 统计信息

实时统计收发包数、速率、错误等

🔧 可配置

丰富的配置选项,适应各种网络环境

🛡️ 错误处理

完善的错误处理机制,自动重试

📝 日志系统

多级别日志,便于调试和监控

🚀 快速开始

1. 创建接收端

#include "udp_receiver.h"

using namespace udp_comm;

int main() {
    // 配置接收端
    UDPReceiver::Config config;
    config.port = 8888;
    config.bindAddr = "0.0.0.0";
    
    UDPReceiver receiver(config);
    
    // 设置回调
    receiver.setCallback([](const Message& msg, const NetAddress& addr) {
        std::cout << "收到消息 from " << addr.toString() << std::endl;
        std::cout << "类型: " << (int)msg.header.type << std::endl;
    });
    
    // 启动
    receiver.start();
    
    // 等待
    std::this_thread::sleep_for(std::chrono::seconds(60));
    receiver.stop();
    
    return 0;
}

2. 创建发送端

#include "udp_sender.h"

using namespace udp_comm;

int main() {
    // 配置发送端
    UDPSender::Config config;
    config.destAddr = "127.0.0.1";
    config.destPort = 8888;
    
    UDPSender sender(config);
    
    // 发送时间戳
    auto ts = TimestampData::now();
    sender.sendStruct(MSG_TIMESTAMP, 1, ts);
    
    return 0;
}
📌 注意: 确保接收端和发送端的端口一致,IP地址正确。

📦 安装

从源码编译

# 克隆仓库
git clone https://github.com/your-repo/udp-comm.git
cd udp-comm

# 创建构建目录
mkdir build && cd build

# 配置CMake
cmake .. -DCMAKE_BUILD_TYPE=Release

# 编译
make -j4

# 安装
sudo make install

CMake集成

# 在项目的CMakeLists.txt中
find_package(udp_comm REQUIRED)

target_link_libraries(your_target 
    udp_comm::udp_receiver 
    udp_comm::udp_sender
)

依赖项

📡 协议规范

消息格式

// 消息头 (12字节)
struct MessageHeader {
    unsigned char header[2];   // 帧头: 0xAA 0xBB
    unsigned char type;         // 消息类型
    unsigned char reserved;     // 保留字段
    uint32_t requestID;         // 请求ID (网络字节序)
    uint32_t dataLength;        // 数据长度 (网络字节序)
};

// 完整消息 = 消息头 + 数据

字节序

字段 字节序 说明
requestID 网络字节序 (大端) 使用htonl/ntohl转换
dataLength 网络字节序 (大端) 使用htonl/ntohl转换
多字节数据 网络字节序 根据数据类型处理

预定义数据类型

// 时间戳消息
struct TimestampData {
    uint16_t year;      // 网络字节序
    uint8_t month;
    uint8_t day;
    uint8_t hour;
    uint8_t minute;
    uint8_t second;
    uint16_t millisecond; // 网络字节序
};

// 传感器数据
struct SensorData {
    float temperature;   // 网络字节序
    float humidity;      // 网络字节序
    float pressure;      // 网络字节序
    uint16_t deviceId;   // 网络字节序
    uint32_t timestamp;  // 网络字节序
};

🔧 API参考

UDPSender 类

构造函数

explicit UDPSender(const Config& config);

创建UDP发送端实例。

主要方法

方法 描述
bool send(const Message& msg) 发送消息到默认目标
bool sendTo(const Message& msg, const NetAddress& dest) 发送消息到指定目标
bool sendRaw(const std::vector<uint8_t>& data) 发送原始数据
bool sendAndReceive(const Message& msg, Message& response, int timeoutMs) 发送并等待响应
template<typename T> bool sendStruct(uint8_t type, uint32_t requestId, const T& payload) 发送结构体数据
Statistics getStatistics() const 获取统计信息

UDPReceiver 类

构造函数

explicit UDPReceiver(const Config& config);

创建UDP接收端实例。

主要方法

方法 描述
bool start() 启动接收
void stop() 停止接收
void setCallback(CallbackFunc callback) 设置消息回调
void addFilter(uint8_t msgType, CallbackFunc callback) 添加消息过滤器
void removeFilter(uint8_t msgType) 移除消息过滤器
Statistics getStatistics() const 获取统计信息

NetAddress 类

方法 描述
NetAddress(const std::string& ip, uint16_t port) 从IP和端口创建
std::string ip() const 获取IP地址
uint16_t port() const 获取端口
std::string toString() const 转换为"ip:port"字符串

Message 类

静态方法 描述
static Message fromBytes(const uint8_t* bytes, size_t len) 从字节流解析消息
static Message create(uint8_t type, uint32_t requestId, const std::vector<uint8_t>& payload = {}) 创建消息
template<typename T> static Message createWithStruct(uint8_t type, uint32_t requestId, const T& payload) 从结构体创建消息
std::vector<uint8_t> toBytes() const 序列化为字节流

⚙️ 配置选项

UDPSender::Config

字段 类型 默认值 说明
destAddr std::string "127.0.0.1" 目标IP地址
destPort uint16_t 8888 目标端口
srcPort uint16_t 0 源端口(0表示自动分配)
bindAddr std::string "0.0.0.0" 绑定地址
ttl int 64 生存时间
enableBroadcast bool false 启用广播
timeoutMs int 1000 发送超时(ms)
bufferSize size_t 65536 缓冲区大小
maxRetries int 3 最大重试次数

UDPReceiver::Config

字段 类型 默认值 说明
port uint16_t 8888 监听端口
bindAddr std::string "0.0.0.0" 绑定地址
timeoutMs int 1000 接收超时(ms)
bufferSize size_t 65536 缓冲区大小
reuseAddr bool true 地址复用
queueSize int 100 消息队列大小
enableStats bool true 启用统计

📨 消息类型

类型值 名称 描述 数据结构
0x00 MSG_HEARTBEAT 心跳消息 无数据
0x01 MSG_TIMESTAMP 时间戳 TimestampData
0x02 MSG_CLICK_COORDINATES 点击坐标 ClickCoordinates
0x03 MSG_TARGET_BOX 目标框 TargetBox
0x04 MSG_SENSOR_DATA 传感器数据 SensorData
0x05 MSG_COMMAND 命令 自定义
0x06 MSG_RESPONSE 响应 自定义
0x07 MSG_ERROR 错误 错误码

💡 示例代码

完整接收端示例

#include "udp_receiver.h"
#include <signal.h>

using namespace udp_comm;

std::atomic<bool> running{true};

void signalHandler(int) {
    running = false;
}

int main() {
    signal(SIGINT, signalHandler);
    
    UDPReceiver::Config config;
    config.port = 8888;
    config.queueSize = 1000;
    
    UDPReceiver receiver(config);
    
    // 时间戳处理器
    receiver.addFilter(MSG_TIMESTAMP, [](const Message& msg, const NetAddress& addr) {
        if (msg.data.size() >= sizeof(TimestampData)) {
            const auto* ts = reinterpret_cast<const TimestampData*>(msg.data.data());
            std::cout << "[" << addr.toString() << "] 时间戳: " 
                      << ntohs(ts->year) << "-" 
                      << (int)ts->month << "-" << (int)ts->day << " "
                      << (int)ts->hour << ":" << (int)ts->minute << ":"
                      << (int)ts->second << "." << ntohs(ts->millisecond)
                      << std::endl;
        }
    });
    
    // 传感器数据处理器
    receiver.addFilter(MSG_SENSOR_DATA, [](const Message& msg, const NetAddress& addr) {
        if (msg.data.size() >= sizeof(SensorData)) {
            const auto* sensor = reinterpret_cast<const SensorData*>(msg.data.data());
            std::cout << "[" << addr.toString() << "] 传感器: "
                      << "温度=" << sensor->temperature << "°C, "
                      << "湿度=" << sensor->humidity << "%, "
                      << "气压=" << sensor->pressure << "hPa"
                      << std::endl;
        }
    });
    
    // 默认处理器
    receiver.setCallback([](const Message& msg, const NetAddress& addr) {
        std::cout << "[" << addr.toString() << "] 未知类型: " 
                  << (int)msg.header.type << ", 大小: " 
                  << msg.data.size() << "字节" << std::endl;
    });
    
    receiver.start();
    std::cout << "接收端已启动,监听端口: " << config.port << std::endl;
    
    while (running) {
        std::this_thread::sleep_for(std::chrono::seconds(1));
        
        // 每10秒显示统计信息
        static int counter = 0;
        if (++counter % 10 == 0) {
            auto stats = receiver.getStatistics();
            std::cout << "\n--- 统计信息 ---\n" << stats.toString() << "\n";
        }
    }
    
    receiver.stop();
    std::cout << "接收端已停止" << std::endl;
    
    return 0;
}

完整发送端示例

#include "udp_sender.h"
#include <random>

using namespace udp_comm;

int main() {
    UDPSender::Config config;
    config.destAddr = "192.168.1.100";
    config.destPort = 8888;
    config.enableStats = true;
    
    UDPSender sender(config);
    
    std::random_device rd;
    std::mt19937 gen(rd());
    std::uniform_real_distribution<> tempDist(15.0, 35.0);
    std::uniform_real_distribution<> humidDist(30.0, 80.0);
    
    uint32_t requestId = 1;
    
    for (int i = 0; i < 100; i++) {
        // 发送时间戳
        auto ts = TimestampData::now();
        sender.sendStruct(MSG_TIMESTAMP, requestId++, ts);
        
        // 发送传感器数据
        SensorData sensor;
        sensor.temperature = tempDist(gen);
        sensor.humidity = humidDist(gen);
        sensor.pressure = 1013.25;
        sensor.deviceId = htons(0x1234);
        sensor.timestamp = htonl(time(nullptr));
        
        sender.sendStruct(MSG_SENSOR_DATA, requestId++, sensor);
        
        std::cout << "已发送 " << (i*2 + 2) << " 条消息" << std::endl;
        std::this_thread::sleep_for(std::chrono::milliseconds(500));
    }
    
    auto stats = sender.getStatistics();
    std::cout << "\n发送完成!\n" << stats.toString() << std::endl;
    
    return 0;
}

🔬 高级用法

请求-响应模式

// 客户端
UDPSender sender(config);
Message request = Message::create(MSG_COMMAND, 1234, commandData);
Message response;

if (sender.sendAndReceive(request, response, 2000)) {
    std::cout << "收到响应,类型: " << (int)response.header.type << std::endl;
} else {
    std::cout << "请求超时" << std::endl;
}

广播模式

UDPSender::Config config;
config.destAddr = "255.255.255.255";
config.destPort = 8888;
config.enableBroadcast = true;

UDPSender sender(config);
sender.send(Message::create(MSG_HEARTBEAT, 1));

多目标发送

UDPSender sender(config);
NetAddress addr1("192.168.1.10", 8888);
NetAddress addr2("192.168.1.20", 8888);

auto msg = Message::create(MSG_TIMESTAMP, 1, data);
sender.sendTo(msg, addr1);
sender.sendTo(msg, addr2);

自定义消息类型

#pragma pack(push, 1)
struct MyCustomData {
    uint32_t id;
    float value;
    char name[32];
};
#pragma pack(pop)

// 发送
MyCustomData data{htonl(100), 3.14f, "sensor1"};
sender.sendStruct(0x10, requestId++, data);

// 接收
receiver.addFilter(0x10, [](const Message& msg, const NetAddress& addr) {
    auto* data = reinterpret_cast<const MyCustomData*>(msg.data.data());
    std::cout << "ID: " << ntohl(data->id) << ", Value: " << data->value << std::endl;
});

🔍 故障排除

问题1: 无法接收数据

可能原因:

  • 端口不匹配 - 检查发送端和接收端端口是否一致
  • 防火墙阻止 - 检查防火墙规则
  • 绑定地址错误 - 使用"0.0.0.0"监听所有接口
  • 网络不通 - 使用ping测试连接

解决方案:

// 接收端监听所有接口
config.bindAddr = "0.0.0.0";

// 发送端使用正确的IP
config.destAddr = "192.168.1.100";  // 接收端实际IP
问题2: 数据解析错误

可能原因:

  • 字节序问题 - 确保使用htonl/ntohl转换多字节数据
  • 结构体对齐 - 使用#pragma pack(1)
  • 数据长度错误 - 检查dataLength字段

解决方案:

// 发送端
uint32_t value = htonl(original_value);

// 接收端
uint32_t value = ntohl(received_value);
问题3: 性能问题

可能原因:

  • 缓冲区太小 - 增加bufferSize
  • 阻塞操作 - 使用非阻塞模式或队列
  • 频繁的拷贝 - 使用移动语义

解决方案:

// 增加缓冲区
config.bufferSize = 1024 * 1024;  // 1MB

// 启用队列异步处理
config.queueSize = 1000;

📊 性能优化

缓冲区调优

场景 推荐bufferSize 说明
小数据包频繁 65536 (64KB) 减少系统调用
大数据包 262144 (256KB) 避免丢包
高带宽 1048576 (1MB) 提高吞吐量

队列大小优化

// 高并发场景
config.queueSize = 10000;

// 实时性要求高
config.queueSize = 100;  // 较小队列减少延迟

系统级优化

# 增加系统UDP缓冲区
sudo sysctl -w net.core.rmem_max=26214400
sudo sysctl -w net.core.rmem_default=26214400
sudo sysctl -w net.core.wmem_max=26214400
sudo sysctl -w net.core.wmem_default=26214400

📝 更新日志

版本 1.0.0 (2026-03-17)

版本 0.9.0 (2026-02-15) - Beta

🤝 贡献指南

欢迎贡献代码、报告问题或提出新功能建议!

开发流程

  1. Fork 仓库
  2. 创建特性分支 (git checkout -b feature/amazing-feature)
  3. 提交更改 (git commit -m 'Add amazing feature')
  4. 推送到分支 (git push origin feature/amazing-feature)
  5. 创建 Pull Request

代码规范

报告问题

使用GitHub Issues报告问题,请包含:

⚖️ 许可证

MIT License

Copyright (c) 2026 UDP Communication Library

Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal in the Software without restriction, including without limitation the rights to use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, and to permit persons to whom the Software is furnished to do so, subject to the following conditions:

The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.

© 2026 UDP Communication Library. All rights reserved.

文档版本: 1.0.0 | 最后更新: 2026-03-17