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 的数据)
}

浙公网安备 33010602011771号