TCP
在 Qt 中,QTcpServer
和 QTcpSocket
是用于实现 TCP 网络通信的核心类。QTcpServer
用于创建 TCP 服务器,监听客户端的连接请求;QTcpSocket
用于实现客户端和服务器之间的数据传输。
通信流程

服务器
-
创建套接字服务器QTcpServer对象
-
通过QTcpServer对象设置监听,即:QTcpServer::listen()
-
基于QTcpServer::newConnection()信号检测是否有新的客户端连接
-
如果有新的客户端连接调用QTcpSocket *QTcpServer::nextPendingConnection()得到通信的套接字对象
-
使用通信的套接字对象QTcpSocket和客户端进行通信
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include<QMessageBox>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this); tcpserver = new QTcpServer(this);
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_openBt_clicked()
{
quint16 port = ui->portEdit->text().toUInt(); // 获取端口号 if (port == 0 || port > 65535) { QMessageBox::warning(this, "错误", "端口号无效!"); return; } if (!tcpserver->listen(QHostAddress::Any, port)) { QMessageBox::warning(this, "错误", "服务器启动失败!"); return; } QMessageBox::information(this, "成功", "服务器已启动!"); connect(tcpserver, &QTcpServer::newConnection, this, [=]() { QTcpSocket *socket = tcpserver->nextPendingConnection(); clientSockets.append(socket); // 将新客户端 socket 加入列表 // 处理客户端数据 connect(socket, &QTcpSocket::readyRead, this, [=]() { QByteArray data = socket->readAll(); ui->recvEdit->appendPlainText("客户端 say:" + data); }); // 处理客户端断开连接 connect(socket, &QTcpSocket::disconnected, this, [=]() { clientSockets.removeOne(socket); // 从列表中移除 socket->deleteLater(); // 释放资源 }); });
}
void MainWindow::on_sendBt_clicked()
{
// 获取输入框中的文本 QString str = ui->sendEdit->text(); // 假设 sendEdit 是 QLineEdit if (str.isEmpty()) { QMessageBox::warning(this, "错误", "发送内容不能为空!"); return; } // 将 QString 转换为 QByteArray QByteArray data = str.toUtf8(); // 遍历所有客户端 socket,发送数据 for (QTcpSocket *socket : clientSockets) { if (socket->state() == QAbstractSocket::ConnectedState) {// 是用于检查 QTcpSocket 是否处于连接状态的条件。 socket->write(data); // 发送数据 } } // 清空输入框 ui->sendEdit->clear();
}
void MainWindow::on_closeBt_clicked()
{
// 关闭服务器,停止监听 tcpserver->close(); // 断开所有客户端连接 for (QTcpSocket *socket : clientSockets) { if (socket->state() == QAbstractSocket::ConnectedState) { socket->disconnectFromHost(); // 断开连接 } socket->deleteLater(); // 释放资源 } // 清空客户端列表 clientSockets.clear(); // 更新 UI 状态 QMessageBox::information(this, "成功", "服务器已关闭!"); ui->recvEdit->appendPlainText("服务器已关闭!");
}
头文件
#include <QTcpServer>
#include <QTcpSocket>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_openBt_clicked();
void on_sendBt_clicked();
void on_closeBt_clicked();
private:
Ui::MainWindow *ui;
QTcpServer *tcpserver;
QList<QTcpSocket*> clientSockets; // 保存所有客户端连接的 socket 列表
};
客户端
-
创建通信的套接字类QTcpSocket对象
-
使用服务器端绑定的IP和端口连接服务器QAbstractSocket::connectToHost()
-
使用QTcpSocket对象和服务器进行通信
#include "ui_mainwindow.h"
#include<QMessageBox>
MainWindow::MainWindow(QWidget *parent) :
QMainWindow(parent), ui(new Ui::MainWindow)
{
ui->setupUi(this); tcpsocket = new QTcpSocket(this); // 连接 socket 的信号和槽 connect(tcpsocket, &QTcpSocket::connected, this, [=]() { QMessageBox::information(this, "成功", "已连接到服务器!"); ui->recvEdit->appendPlainText("已连接到服务器!"); }); connect(tcpsocket, &QTcpSocket::disconnected, this, [=]() { QMessageBox::information(this, "提示", "已断开与服务器的连接!"); ui->recvEdit->appendPlainText("已断开与服务器的连接!"); }); connect(tcpsocket, &QTcpSocket::readyRead, this, [=]() { QByteArray data = tcpsocket->readAll(); ui->recvEdit->appendPlainText("服务器 say: " + QString::fromUtf8(data)); });
}
MainWindow::~MainWindow()
{
delete ui;
}
void MainWindow::on_connect_clicked()
{
// 获取服务器地址和端口号 QString address = ui->IPEdit->text(); quint16 port = ui->portEdit->text().toUInt(); if (address.isEmpty() || port == 0) { QMessageBox::warning(this, "错误", "服务器地址或端口号无效!"); return; } // 连接到服务器 tcpsocket->connectToHost(address, port); // 检查连接状态 if (!tcpsocket->waitForConnected(1000)) { QMessageBox::warning(this, "错误", "连接服务器超时!"); }
}
void MainWindow::on_disconnect_clicked()
{
// 断开与服务器的连接 if (tcpsocket->state() == QAbstractSocket::ConnectedState) { tcpsocket->disconnectFromHost(); }
}
void MainWindow::on_sendBt_clicked()
{
// 获取输入框中的文本 QString str = ui->sendEdit->text(); // 假设 sendEdit 是 QLineEdit if (str.isEmpty()) { QMessageBox::warning(this, "错误", "发送内容不能为空!"); return; } // 将 QString 转换为 QByteArray QByteArray data = str.toUtf8(); // 发送数据 if (tcpsocket->state() == QAbstractSocket::ConnectedState) { tcpsocket->write(data); } else { QMessageBox::warning(this, "错误", "未连接到服务器!"); } // 清空输入框 ui->sendEdit->clear();
}
头文件
#include <QTcpSocket>
namespace Ui {
class MainWindow;
}
class MainWindow : public QMainWindow
{
Q_OBJECT
public:
explicit MainWindow(QWidget *parent = 0);
~MainWindow();
private slots:
void on_sendBt_clicked();
void on_connect_clicked();
void on_disconnect_clicked();
private:
Ui::MainWindow *ui;
QTcpSocket* tcpsocket; // 保存所有客户端连接的 socket 列表
};

作者: 苏丙榅
来源: 爱编程的大丙
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。