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

来源: 爱编程的大丙

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

相关推荐
Larry_Yanan2 小时前
QML学习笔记(三十一)QML的Flow定位器
java·前端·javascript·笔记·qt·学习·ui
Larry_Yanan3 小时前
QML学习笔记(三十)QML的布局器(Layouts)
c++·笔记·qt·学习·ui
feiyangqingyun3 小时前
Qt编写上下界面切换效果/前进到下一个界面/后退到上一个页面/零件工艺及管理设计系统
qt·零件工艺
ajassi20003 小时前
开源 C++ QT QML 开发(十五)通讯--http下载
c++·qt·开源
枫叶丹45 小时前
【Qt开发】输入类控件(六)-> QDial
开发语言·qt
咯哦哦哦哦7 小时前
关于QT 打印中文 乱码问题
java·数据库·qt
mark-puls7 小时前
Qt界面布局利器:QStackedWidget详细用法解析
开发语言·qt
执尺量北斗11 小时前
LinkMate 智能会议室系统:基于 Qt / QML / WebRTC / FFmpeg / Whisper / OpenGL 的实时音视频会议平台
qt·ffmpeg·webrtc
共享家952721 小时前
QT-常用控件(二)
开发语言·qt
江公望1 天前
Qt QThread使用方法入门浅解
c++·qt