QT 网络编程QTcpServer服务端
QTcpServer
Qt的QTcpServer
是用于创建TCP服务器端的核心类,基于事件驱动模型实现,支持监听客户端连接并处理网络通信。
QTcpServer的核心功能#
- 监听连接:通过指定IP地址和端口号,服务器可以监听客户端的连接请求。
- 接受连接:当客户端发起连接请求时,
QTcpServer
会创建QTcpSocket
对象来处理通信。 - 信号驱动:基于Qt的事件循环和信号槽机制,实现异步通信。
- 通过
newConnection()
信号通知接入请求。
- 通过
基础使用步骤#
在项目.pro
文件中添加network
,即:
QT += network
创建并启动服务器#
创建QTcpServer实例后调用listen(ip地址, 端口号)
启动服务器
- 注意:IP地址为
QHostAddress
对象,不可直接写入字符串
QTcpServer *server = new QTcpServer(this); if(!server->listen(QHostAddress::Any, 12345)){ qDebug() << "server could not start: " << server->errorString(); }else { qDebug() << "Server listening on port 12345..."; }
其中QHostAddress::Any
表示监听所有可用IPv4地址,若需IPv6可使用QHostAddress::AnyIPv6
。
listen()
返回bool
值,失败时,可调用errorString()
获取错误信息。
关键信号与方法#
信号名称 | 触发条件 | 典型应用场景 |
---|---|---|
newConnection() | 有新客户端完成TCP三次握手 | 启动客户端会话管理 |
acceptError() | 接受连接时发生系统级错误 | 错误日志记录和报警 |
destoryed() | 服务器对象销毁时 | 资源释放验证 |
方法名称 | 说明 |
---|---|
listen(QHostAddress, port) | 启动服务器监听 |
isListening() | 检查是否正在监听 |
serverPort() | 获取实际绑定的端口 |
nextPendingConnection() | 获取下一个等待连接的客户端 |
close() | 关闭现有服务,但已经连接的Socket需要手动管理(不会自动断开) |
处理新连接信号#
当客户端连接时,QTcpServer
会触发newConnection()
信号,通过该信号绑定槽函数。
connect(server, &QTcpServer::newConnection, this, &MyServer::handleNewConnection);
获取连接的Socket对象#
在槽函数中通过nextPendingConnection()
获取客户端Socket:
void MyServer::handleNewConnection(){ QTcpSocket *clientSocket = server->nextPendingConnection(); // 存储或管理clientSocket,例如加入列表 connect(clientSocket, &QTcpSocket::readyRead, this, &MyServer::readData); // 读取客户端传来的信息 // 断开连接后 移除socket释放内存 connect(clientSocket, &QTcpSocket::disconnected, clientSocket, &QTcpSocket::deleteLater); }
- 生命周期管理:连接断开后,使用
deleteLater()
自动释放内存。 - 多客户端处理:通常使用容器(如
QList<QTcpSocket*>
)管理多个客户端。
数据传输(QTcpSocket)#
读取数据#
通过readyRead()
信号触发读取:
void MyServer::readData(){ QTcpSocket *socket = qobject_cast<QTcpSocket*>(sender()); QByteArray data = socket->readAll(); qDebug() << "received:" << data; }
- 通过
QByteArray
接收的结果无法显示中文信息,可以通过QString utf8Text = QString::fromUtf8(data);
将其转换为utf-8格式的字符串,即可显示中文信息 - 数据分片处理:TCP是流协议,需自行处理数据边界(如定义长度前缀或分隔符)。
发送数据#
使用write()
发送数据:
QByteArray response = "Hello Client!"; socket->write(response); socket->flush(); //可选,立即发送数据
错误处理#
监听Socket的错误信息:
connect(clientSocket, &QTcpSocket::errorOccurred, [=](QAbstractSocket::SocketError error){ qDebug() << "Socket Error:" << clientSocket->errorString(); });
线程问题#
Qt的事件循环默认在单线程中处理事件,而QTcpServer
是异步的,即在处理前一个客户端的数据时,也能够接受后续客户端的连接(在处理客户端数据的函数中未使用同步阻塞操作如waitForReadyRead()
或耗时计算),即在默认情况下,QTcpServer
也能同时连接多个客户端(低并发)。
原理#
- 操作系统监听队列
- 当
QTcpServer
调用listen()
时,底层会通过操作系统API(如listen()
in POSIX)创建一个监听队列(backlog)。 - 操作系统会自动缓存未处理的连接请求(已完成TCP三次握手的连接),队列长度通常由
server.setMaxPendingConnections()
控制(默认30)。
- 当
- 事件循环的非阻塞性
- Qt的事件循环(
QEventLoop
)通过非阻塞的机制监听socket事件。 - 当新连接到达时,操作系统会通知Qt,
QTcpServer
触发newConnection
信号,但不会阻塞主线程。
- Qt的事件循环(
简化的伪代码逻辑:
// 简化的伪代码逻辑 while (QApplication::eventLoop()->isRunning()) { // 通过 select/poll/epoll 监听所有 socket int ret = os_sys_wait_for_events(fds, timeout); if (有新的连接到达监听 socket) { // 将新连接加入操作系统 accept 队列 enqueue_new_connection(); // 触发 Qt 信号 emit newConnection(); } // 处理其他事件(如已连接 socket 的数据) }
【推荐】国内首个AI IDE,深度理解中文开发场景,立即下载体验Trae
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)