UDP通信库 v1.0.0
一个功能强大、易于使用的C++ UDP通信库,支持多线程、消息过滤、统计信息等功能。
📖 概述
UDP通信库是一个现代化的C++网络编程库,提供了完整的UDP通信解决方案。它封装了底层的socket操作,提供了高级的API接口,使开发者能够快速构建可靠的UDP通信应用。
核心组件
- UDPSender - 高性能UDP发送端,支持多目标发送
- UDPReceiver - 灵活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;
}
📦 安装
从源码编译
# 克隆仓库
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
)
依赖项
- C++17兼容的编译器 (GCC 7+, Clang 5+, MSVC 2017+)
- CMake 3.16+
- POSIX线程库 (pthread)
📡 协议规范
消息格式
// 消息头 (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 类
构造函数
创建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 类
构造函数
创建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;
});
🔍 故障排除
可能原因:
- 端口不匹配 - 检查发送端和接收端端口是否一致
- 防火墙阻止 - 检查防火墙规则
- 绑定地址错误 - 使用"0.0.0.0"监听所有接口
- 网络不通 - 使用ping测试连接
解决方案:
// 接收端监听所有接口
config.bindAddr = "0.0.0.0";
// 发送端使用正确的IP
config.destAddr = "192.168.1.100"; // 接收端实际IP
可能原因:
- 字节序问题 - 确保使用htonl/ntohl转换多字节数据
- 结构体对齐 - 使用#pragma pack(1)
- 数据长度错误 - 检查dataLength字段
解决方案:
// 发送端
uint32_t value = htonl(original_value);
// 接收端
uint32_t value = ntohl(received_value);
可能原因:
- 缓冲区太小 - 增加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)
- ✨ 初始发布
- 📦 完整的UDP收发功能
- 🔧 支持消息过滤和回调
- 📊 实时统计信息
- ⚡ 多线程异步处理
- 🛡️ 错误处理和重试机制
版本 0.9.0 (2026-02-15) - Beta
- 🔨 基础UDP通信功能
- 🐛 Bug修复和性能优化
🤝 贡献指南
欢迎贡献代码、报告问题或提出新功能建议!
开发流程
- Fork 仓库
- 创建特性分支 (
git checkout -b feature/amazing-feature) - 提交更改 (
git commit -m 'Add amazing feature') - 推送到分支 (
git push origin feature/amazing-feature) - 创建 Pull Request
代码规范
- 使用C++17标准
- 遵循Google C++风格指南
- 添加单元测试
- 更新文档
报告问题
使用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