QT 网络编程QTcpServer服务端

风陵南·2025-02-19 11:29·17 次阅读

QT 网络编程QTcpServer服务端

QTcpServer

Qt的QTcpServer是用于创建TCP服务器端的核心类,基于事件驱动模型实现,支持监听客户端连接并处理网络通信。

QTcpServer的核心功能#

  • 监听连接:通过指定IP地址和端口号,服务器可以监听客户端的连接请求。
  • 接受连接:当客户端发起连接请求时,QTcpServer会创建QTcpSocket对象来处理通信。
  • 信号驱动:基于Qt的事件循环和信号槽机制,实现异步通信。
    • 通过newConnection()信号通知接入请求。

基础使用步骤#

在项目.pro文件中添加network,即:

Copy
QT += network

创建并启动服务器#

创建QTcpServer实例后调用listen(ip地址, 端口号)启动服务器

  • 注意:IP地址为QHostAddress对象,不可直接写入字符串
Copy
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()信号,通过该信号绑定槽函数。

Copy
connect(server, &QTcpServer::newConnection, this, &MyServer::handleNewConnection);

获取连接的Socket对象#

在槽函数中通过nextPendingConnection()获取客户端Socket:

Copy
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()信号触发读取:

Copy
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()发送数据:

Copy
QByteArray response = "Hello Client!";
socket->write(response);
socket->flush(); //可选,立即发送数据

错误处理#

监听Socket的错误信息:

Copy
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信号,但不会阻塞主线程。

简化的伪代码逻辑:

Copy
// 简化的伪代码逻辑
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 的数据)
}
posted @   风陵南  阅读(17)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 分享4款.NET开源、免费、实用的商城系统
· 全程不用写代码,我用AI程序员写了一个飞机大战
· MongoDB 8.0这个新功能碉堡了,比商业数据库还牛
· 白话解读 Dapr 1.15:你的「微服务管家」又秀新绝活了
· 上周热点回顾(2.24-3.2)
点击右上角即可分享
微信分享提示
目录