QProtocolUnit 是一个基于 Qt 的网络通信组件,封装了 TCP 客户端、TCP 服务端、UDP 通信、HTTP 请求和可中断线程模型。项目可用于 Qt 工程中的通信模块集成,也提供 Qt Widgets 示例界面用于调试 TCP/UDP 数据收发。
日志模块 QCuteLogger 基于 GitHub 上的开源项目 CuteLogger 集成和适配。
- TCP 服务端:基于
QTcpServer,每个客户端连接由独立线程管理。 - TCP 客户端:支持连接、断开、重连、连接状态通知和数据收发。
- UDP 通信:支持单播、广播、组播,并支持指定网卡。
- HTTP 请求:封装 GET、POST、Header、Cookie 等常用操作。
- 可中断线程:提供线程启动、暂停、恢复、退出和事件循环支持。
- 日志模块:集成
QCuteLogger,用于控制台、文件和滚动日志输出。
.
├── CommonBase.pri
├── QProtocolUnit/
│ ├── inc/ # 通信组件头文件
│ ├── src/ # 通信组件实现与示例入口
│ ├── ui/ # TCP/UDP 示例界面
│ ├── QProtocolUnit.pro # 示例程序工程
│ ├── QProtocolUnit_inc.pri # 头文件引用配置
│ └── QProtocolUnit_src.pri # 源文件引用配置
└── QCuteLogger/
├── inc/ # 日志模块头文件
├── src/ # 日志模块实现
└── QCuteLogger.pro # 日志库工程
- Qt 5 或 Qt 6
- qmake
- C++11
- Qt 模块:
coreguiwidgetsnetworksqlconcurrent
Qt 6 下 QCuteLogger 会额外使用:
core5compat当前 QProtocolUnit.pro 默认配置为示例程序:
TEMPLATE = app
TARGET = QProtocolUnit建议先构建日志库,再构建示例程序。
- 打开
QCuteLogger/QCuteLogger.pro并构建。 - 打开
QProtocolUnit/QProtocolUnit.pro并构建运行。
cd QCuteLogger
qmake QCuteLogger.pro
makecd ../QProtocolUnit
qmake QProtocolUnit.pro
makeWindows 下根据编译器使用对应命令:
mingw32-make或:
nmake构建输出目录由 CommonBase.pri 控制:
- MSVC:
bin-msvc - MinGW:
bin-mingw - Debug 目标默认追加
d后缀,例如QProtocolUnitd、QCuteLoggerd
在业务工程 .pro 中引入源码配置:
QT += core gui widgets network sql concurrent
CONFIG += c++11
include(path/to/QProtocolUnit/QProtocolUnit/QProtocolUnit_src.pri)
include(path/to/QProtocolUnit/QCuteLogger/QCuteLogger_src.pri)如果业务工程不需要示例界面,可以只引入核心通信类对应的 .h/.cpp 文件:
interruptthreadclientthreadclientsocketserversocketudpthreadudpsockethttpclient
如果已将模块构建为库,可在业务工程中加入:
INCLUDEPATH += path/to/QProtocolUnit/QProtocolUnit/inc
INCLUDEPATH += path/to/QProtocolUnit/QCuteLogger/inc
LIBS += -Lpath/to/bin -lQProtocolUnit
LIBS += -Lpath/to/bin -lQCuteLoggerDebug 版本按当前命名规则使用:
LIBS += -lQProtocolUnitd
LIBS += -lQCuteLoggerd#include "serversocket.h"
ServerSocket server;
server.startServer(5130);
connect(&server, &ServerSocket::sig_newClient,
[](QString host, int port) {
qDebug() << "new client:" << host << port;
});
connect(&server, &ServerSocket::sig_newMsg,
[](QString host, int port, QByteArray data) {
qDebug() << "recv:" << host << port << data;
});
server.writeToClient("hello", "127.0.0.1", 50000);#include "clientthread.h"
ClientThread *client = new ClientThread(socket_client);
client->setClient(nullptr, "127.0.0.1", 5130);
connect(client, &ClientThread::sig_receiveData,
[](QString host, int port, QByteArray data) {
qDebug() << "recv from server:" << host << port << data;
});
connect(client, &ClientThread::sig_stateChanged,
[](QString host, int port, int state) {
qDebug() << "state:" << host << port << state;
});
client->createThread();
client->startThread();
client->appendDataToClient("hello server");#include "udpthread.h"
UDPThread *udp = new UDPThread;
udp->setClient(
nullptr,
"192.168.0.100", // 目标地址
8880, // 目标端口
8881 // 本地端口
);
connect(udp, &UDPThread::sig_receiveData,
[](QString host, QByteArray data) {
qDebug() << "udp recv:" << host << data;
});
udp->createThread();
udp->startThread();
udp->appendDataToClient("hello udp");udp->setClient(
nullptr,
"239.255.0.1",
8888,
8888,
broad_group
);如需指定网卡,可传入 QNetworkInterface:
QNetworkInterface net = QNetworkInterface::interfaceFromName("eth0");
udp->setClient(
nullptr,
"239.255.0.1",
8888,
8888,
broad_group,
net
);#include "httpclient.h"
QMap<QString, QString> headers;
headers.insert("User-Agent", "QProtocolUnit");
QByteArray data = getClientHandler()->get("https://example.com", headers);
qDebug() << data;POST 示例:
QByteArray body = R"({"name":"test"})";
QByteArray reply = getClientHandler()->postData("https://example.com/api", body);| 类 | 说明 |
|---|---|
InterruptThread |
可中断线程基类,提供启动、暂停、恢复、退出能力 |
ClientThread |
TCP 连接线程,负责单个 TCP 连接的数据收发 |
ClientSocket |
TCP Socket 封装,通常由 ClientThread 内部使用 |
ServerSocket |
TCP 服务端,负责监听、接入控制和客户端线程管理 |
UDPThread |
UDP 通信线程 |
UDPSocket |
UDP Socket 封装,支持单播、广播、组播 |
HttpClient |
HTTP 请求封装 |
HttpClientHandler |
HTTP 请求便捷调用封装 |
ClientTableViewModel |
示例界面中使用的客户端列表模型 |
ClientThread 和 UDPThread 推荐按以下顺序使用:
setClient(...);
createThread();
startThread();closeClient():关闭当前连接,但保留连接线程。openClient():重新打开已关闭的连接。deleteClient():删除连接并结束线程。appendDataToClient():向发送队列追加数据,适合跨线程发送。
ServerSocket 支持按 IP 或 IP + Port 管理客户端连接:
server.stopClient("127.0.0.1");
server.stopClient("127.0.0.1", 50000);
server.delClient("127.0.0.1");
server.delClient("127.0.0.1", 50000);服务端也支持黑白名单:
server.addClientToBlackList("192.168.1.10");
server.removeClientFromBlackList("192.168.1.10");
server.addClientToWhiteList("192.168.1.20");
server.removeClientFromWhiteList("192.168.1.20");ClientSocket应在线程内部使用,不建议在主线程直接调用。ServerSocket的管理接口建议在主线程调用。- 跨线程发送数据时,优先使用信号槽或
appendDataToClient()。
UDP 是无连接协议,发送成功只表示数据已交给系统发送,不代表对端一定收到。组播模式下需要确认本机网卡、组播地址和端口配置正确。
QProtocolUnit 示例程序启动两个界面:
ProtocolForm:TCP 服务端/客户端调试界面。UDPForm:UDP 单播、组播调试界面。
示例程序可用于验证本地端口监听、客户端连接、数据收发、连接状态变化和组播网卡选择。
本项目包含并适配了以下第三方开源组件:
| 组件 | 来源 | 说明 |
|---|---|---|
QCuteLogger / CuteLogger |
dept2/CuteLogger | Qt 日志组件,本项目中用于日志输出,并做了工程结构和 Qt 版本适配 |
如需了解 CuteLogger 的原始实现和授权信息,请参考其上游仓库。
本项目使用 MIT License 发布。详情见 LICENSE。
项目中集成的第三方组件仍遵循其原始许可证要求。