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 列表
};
作者: 苏丙榅
链接: 基于TCP的Qt网络通信 | 爱编程的大丙
来源: 爱编程的大丙
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。