当前位置: 首页 > news >正文

通信TCP

  • TCP
    • 通信流程
    • 服务器
    • 客户端

TCP

在 Qt 中,QTcpServer 和 QTcpSocket 是用于实现 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网络通信 | 爱编程的大丙
来源: 爱编程的大丙
著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

相关文章:

  • 2025 年:SAP 咨询的关键转折点
  • Linux 命令行的基本命令(生信)
  • 蓝桥杯第15届真题解析
  • JAVA面经2
  • webpack一篇
  • Java 大视界 -- Java 大数据在智能医疗远程诊断中的技术支撑与挑战(106)
  • Linux虚拟机网络配置-桥接网络配置
  • 一篇文章说清楚OKR
  • 4G工业路由器在公交充电桩中的应用与优势
  • 【三.大模型实战应用篇】【3.智能学员辅导系统:docx文档处理技巧】
  • Tauri跨平台应用开发深度解析与实战指南
  • arm | lrzsz移植记录
  • 多线程学习之路
  • 阿里云服务器部署项目笔记 实操 centos7.9
  • 《C++ primer》第二章
  • 一、C++上岸教程—C语言基础
  • CentOS 7 IP 地址设置保姆级教程
  • playbin之Source插件加载流程源码剖析
  • 2024_BUAA数据结构上机题解分享
  • 03.03 QT
  • 韩代总统李周浩履职
  • 中国队夺跳水世界杯总决赛首金
  • 生命与大海相连:他在300多米的深海行走,在沉船一线打捞救援
  • 金融监管总局修订发布《行政处罚办法》,7月1日起施行
  • 国台办:民进党当局所谓“对等尊严”,就是企图改变两岸同属一中
  • 新经济与法|如何治理网购刷单与控评?数据合规管理是关键