通信TCP

TCP

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

通信流程

服务器

  1. 创建套接字服务器QTcpServer对象

  2. 通过QTcpServer对象设置监听,即:QTcpServer::listen()

  3. 基于QTcpServer::newConnection()信号检测是否有新的客户端连接

  4. 如果有新的客户端连接调用QTcpSocket *QTcpServer::nextPendingConnection()得到通信的套接字对象

  5. 使用通信的套接字对象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 列表

};

客户端

  1. 创建通信的套接字类QTcpSocket对象

  2. 使用服务器端绑定的IP和端口连接服务器QAbstractSocket::connectToHost()

  3. 使用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网络通信 | 爱编程的大丙

来源: 爱编程的大丙

著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关推荐
一叶之秋141214 小时前
QT背景介绍与环境搭建
开发语言·qt
QT 小鲜肉15 小时前
【QT/C++】Qt网络编程进阶:UDP通信和HTTP请求的基本原理和实际应用(超详细)
c语言·网络·c++·笔记·qt·http·udp
四维碎片18 小时前
【Qt】大数据量表格刷新优化--只刷新可见区域
开发语言·qt
一叶之秋141220 小时前
Qt开发初识
开发语言·qt
梵尔纳多21 小时前
ffmpeg 使用滤镜实现播放倍速
c++·qt·ffmpeg
QT 小鲜肉1 天前
【QT/C++】Qt网络编程进阶:TCP网络编程的基本原理和实际应用(超详细)
c语言·开发语言·网络·c++·qt·学习·tcp/ip
Tony小周1 天前
使用QKeyEvent keyPress(QEvent::KeyPress, key模拟键盘发送事件,会导致主程序卡死
嵌入式硬件·qt
Larry_Yanan1 天前
QML学习笔记(五十)QML与C++交互:QML中单例C++对象
开发语言·c++·笔记·qt·学习·ui·交互
zhmhbest2 天前
Qt 全球峰会 2025:中国站速递 —— 技术中立,拥抱更大生态
开发语言·qt·系统架构
feiyangqingyun2 天前
Qt实时绘制飞行轨迹/移动轨迹实时显示/带旋转角度/平滑移动/效果一级棒/地面站软件开发/无人机管理平台
qt·无人机·集群地面站