通信流程 2个月前

编程语言
347
通信流程

通信流程

使用Qt提供的类进行套接字通信比使用标准C API进行网络通信要简单(因为在内部进行了封装) Qt中的套接字通信流程如下:

1. 服务器端

1.1 通信流程

  1. 创建套接字服务器QTcpServer对象
  2. 通过QTcpServer对象设置监听,即:QTcpServer::listen()
  3. 基于QTcpServer::newConnection()信号检测是否有新的客户端连接
  4. 如果有新的客户端连接调用QTcpSocket *QTcpServer::nextPendingConnection()得到通信的套接字对象
  5. 使用通信的套接字对象QTcpSocket和客户端进行通信

1.2 代码片段

服务器端的窗口界面如下图所示:

image

头文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpServer>
#include <QTcpSocket>
#include <QLabel>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:

    void on_startBtn_clicked();

    void on_sendBtn_clicked();

private:
    Ui::MainWindow *ui;
    QTcpServer* m_server;
    QTcpSocket* m_tcp;
    QLabel* m_status;
};
#endif // MAINWINDOW_H

源文件

#include "mainwindow.h"
#include "ui_mainwindow.h"


MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    setWindowTitle("Tcp - Server");

    //创建QServer对象
    m_server = new QTcpServer(this);

    //检测是否有新的客户端连接
    connect(m_server,&QTcpServer::newConnection,this,[=](){
        m_tcp = m_server->nextPendingConnection();
        //连接成功后更新历史记录和底部状态栏
        ui->record->append("connect sucessfully");
        m_status->setPixmap(QPixmap(":/bingo").scaled(20,20));


        //检测客户端是否发送数据
        connect(m_tcp,&QTcpSocket::readyRead,this,[=](){
            QString recvmsg = m_tcp->readAll();
            ui->record->append("client say : " + recvmsg);
        });

        connect(m_tcp,&QTcpSocket::disconnected,this,[=](){
            ui->record->append("disconnect...");
            m_tcp->close();
            m_tcp->deleteLater();
            m_status->setPixmap(QPixmap(":/wrong").scaled(20,20));
        });
    });
    m_status = new QLabel;
    m_status->setPixmap(QPixmap(":/wrong").scaled(20,20));
    ui->statusbar->addWidget(new QLabel("connect status : "));
    ui->statusbar->addWidget(m_status);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_startBtn_clicked()
{
    unsigned short port = ui->port->text().toInt();

    //设置服务器监听
    m_server->listen(QHostAddress::Any,port);
    ui->startBtn->setEnabled(false);
}


void MainWindow::on_sendBtn_clicked()
{
    QString sendmsg = ui->msg->toPlainText();
    m_tcp->write(sendmsg.toUtf8());
    ui->record->append("server say : " +sendmsg);
    ui->msg->clear();
}

2. 客户端

2.1 通信流程

  1. 创建通信的套接字类QTcpSocket对象
  2. 使用服务器端绑定的IP和端口连接服务器QAbstractSocket::connectToHost()
  3. 使用QTcpSocket对象和服务器进行通信

2.2 代码片段

客户端的窗口界面如下图所示:

image

头文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QTcpSocket>
#include <QLabel>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    MainWindow(QWidget *parent = nullptr);
    ~MainWindow();

private slots:
    void on_conBtn_clicked();

    void on_disBtn_clicked();

    void on_sendBtn_clicked();

private:
    Ui::MainWindow *ui;
    QTcpSocket* m_tcp;
    QLabel* m_status;
};
#endif // MAINWINDOW_H

源文件

#include "mainwindow.h"
#include "ui_mainwindow.h"

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{
    ui->setupUi(this);

    setWindowTitle("Tcp - client");
    //创建套接字对象
    m_tcp = new QTcpSocket(this);


    //接受服务器的消息
    connect(m_tcp,&QTcpSocket::readyRead,this,[=](){
        QString recvmsg = m_tcp->readAll();
        ui->record->append("server say : " + recvmsg);
    });

    //是否和服务器连接成功
    connect(m_tcp,&QTcpSocket::connected,this,[=](){
        ui->record->append("connect sucessfully");
        m_status->setPixmap(QPixmap(":/bingo").scaled(20,20));
    });

    //检测是否断开连接
    connect(m_tcp,&QTcpSocket::disconnected,this,[=](){
        ui->record->append("disconnect......");
        ui->disBtn->setEnabled(false);
        ui->conBtn->setEnabled(true);
        m_status->setPixmap(QPixmap(":/wrong").scaled(20,20));
    });

    m_status = new QLabel;
    m_status->setPixmap(QPixmap(":/wrong").scaled(20,20));
    ui->statusbar->addWidget(new QLabel("connect status : "));
    ui->statusbar->addWidget(m_status);
}

MainWindow::~MainWindow()
{
    delete ui;
}


void MainWindow::on_conBtn_clicked()
{
    QString ip = ui->Ip->text();
    unsigned short port_tmp = ui->port->text().toInt();

    //连接服务器
    m_tcp->connectToHost(QHostAddress(ip),port_tmp);
    ui->conBtn->setEnabled(false);
    ui->disBtn->setEnabled(true);
}


void MainWindow::on_disBtn_clicked()
{
    m_tcp->close();
    ui->disBtn->setEnabled(false);
    ui->conBtn->setEnabled(true);
}


void MainWindow::on_sendBtn_clicked()
{
    QString sendmsg = ui->msg->toPlainText();
    m_tcp->write(sendmsg.toUtf8());
    ui->record->append("client say : " + sendmsg);
    ui->msg->clear();
}
image
EchoEcho官方
无论前方如何,请不要后悔与我相遇。
1377
发布数
439
关注者
2222940
累计阅读

热门教程文档

Docker
62小节
Lua
21小节
Spring Cloud
8小节
Java
12小节
C
14小节