通信TCP

发布于:2025-03-04 ⋅ 阅读:(14) ⋅ 点赞:(0)

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


网站公告

今日签到

点亮在社区的每一天
去签到