首页 > 其他分享 >Qt下的基本TCP网络通信流程

Qt下的基本TCP网络通信流程

时间:2023-08-14 21:12:27浏览次数:37  
标签:网络通信 QTcpServer Qt void TCP ui tcp QTcpSocket MainWindow

给大家讲一下如何使用Qt相关类的进行TCP通信。前置知识:c++基础、qt基础、网络基础

使用Qt提供的类进行基于TCP的套接字通信需要用到两个类:

QTcpServer:服务器类,用于监听客户端连接以及和客户端建立连接。
QTcpSocket:通信的套接字类,客户端、服务器端都需要使用。
这两个套接字通信类都属于网络模块network。所以需要加入对应的network模块。

image-20230814203032513

其实无论哪个语言,通信的流程都是大差不差的

1.QTcpServer

QTcpServer类用于监听客户端连接以及和客户端建立连接,在使用之前先介绍一下这个类提供的一些常用API函数:

1.1构造函数

QTcpServer::QTcpServer(QObject *parent = Q_NULLPTR);

设置监听

bool QTcpServer::listen(const QHostAddress &address = QHostAddress::Any, quint16 port = 0);
// 判断当前对象是否在监听, 是返回true,没有监听返回false
bool QTcpServer::isListening() const;
// 如果当前对象正在监听返回监听的服务器地址信息, 否则返回 QHostAddress::Null
QHostAddress QTcpServer::serverAddress() const;
// 如果服务器正在侦听连接,则返回服务器的端口; 否则返回0
quint16 QTcpServer::serverPort() const

参数:
address:通过类QHostAddress可以封装IPv4、IPv6格式的IP地址,QHostAddress::Any表示自动绑定
port:如果指定为0表示随机绑定一个可用端口。
返回值:绑定成功返回true,失败返回false

得到和客户端建立连接之后用于通信的QTcpSocket套接字对象,它是QTcpServer的一个子对象,当QTcpServer对象析构的时候会自动析构这个子对象,当然也可自己手动析构,建议用完之后自己手动析构这个通信的QTcpSocket对象。

QTcpSocket *QTcpServer::nextPendingConnection();

如果了解Linux网络编程的话就会理解,其实这就是相当于accept函数,返回一个socket

1.2信号

当接受新连接导致错误时,将发射如下信号。socketError参数描述了发生的错误相关的信息。

[signal] void QTcpServer::acceptError(QAbstractSocket::SocketError socketError);

每次有新连接可用时都会发出 newConnection() 信号。

[signal] void QTcpServer::newConnection();

2.QTcpSocket

QTcpSocket是一个套接字通信类,不管是客户端还是服务器端都需要使用。在Qt中发送和接收数据也属于IO操作(网络IO)。

2.1

构造函数

QTcpSocket::QTcpSocket(QObject *parent = Q_NULLPTR);

连接服务器,需要指定服务器端绑定的IP和端口信息。

[virtual] void QAbstractSocket::connectToHost(const QString &hostName, quint16 port, OpenMode openMode = ReadWrite, NetworkLayerProtocol protocol = AnyIPProtocol);

[virtual] void QAbstractSocket::connectToHost(const QHostAddress &address, quint16 port, OpenMode openMode = ReadWrite);

在Qt中不管调用读操作函数接收数据,还是调用写函数发送数据,操作的对象都是本地的由Qt框架维护的一块内存。因此,调用了发送函数数据不一定会马上被发送到网络中,调用了接收函数也不是直接从网络中接收数据,关于底层的相关操作是不需要使用者来维护的。这其实是与Linux类似的,也是维护一片缓冲区内存用于通信。

接收数据

// 指定可接收的最大字节数 maxSize 的数据到指针 data 指向的内存中
qint64 QIODevice::read(char *data, qint64 maxSize);
// 指定可接收的最大字节数 maxSize,返回接收的字符串
QByteArray QIODevice::read(qint64 maxSize);
// 将当前可用操作数据全部读出,通过返回值返回读出的字符串
QByteArray QIODevice::readAll();

发送数据

// 发送指针 data 指向的内存中的 maxSize 个字节的数据
qint64 QIODevice::write(const char *data, qint64 maxSize);
// 发送指针 data 指向的内存中的数据,字符串以 \0 作为结束标记
qint64 QIODevice::write(const char *data);
// 发送参数指定的字符串
qint64 QIODevice::write(const QByteArray &byteArray);

2.2信号

在使用QTcpSocket进行套接字通信的过程中,如果该类对象发射出readyRead()信号,说明对端发送的数据达到了,之后就可以调用 read 函数接收数据了。

[signal] void QIODevice::readyRead();

调用connectToHost()函数并成功建立连接之后发出connected()信号。

[signal] void QAbstractSocket::connected();

在套接字断开连接时发出disconnected()信号。

[signal] void QAbstractSocket::disconnected();

3.通信流程

3.1服务器端

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

3.1.2代码片段

服务器端如图

image-20230814205236113

头文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

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

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:
    void on_setlisten_clicked();

    void on_sendmsg_clicked();

private:
    Ui::MainWindow *ui;
    QTcpServer *m_s;
    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);
    ui->port->setText("9527");
    //实例化
    m_s = new QTcpServer(this);

    connect(m_s,&QTcpServer::newConnection,this,[=](){
        m_tcp = m_s->nextPendingConnection();
        //修改图片
        m_status->setPixmap(QPixmap(":/OIP-C.jpg").scaled(20,20));
        //检测
        connect(m_tcp,&QTcpSocket::readyRead,this,[=](){
            QByteArray data = m_tcp->readAll();
            ui->record->append("客户端发来:"+data);
        });

        //检测是否断开连接
        connect(m_tcp,&QTcpSocket::disconnected,this,[=](){
            m_tcp->close();
            m_tcp->deleteLater();     //封装后的delete
            m_status->setPixmap(QPixmap(":/th.jpg").scaled(20,20));
        });

    });


    //状态栏
    m_status = new QLabel;
    m_status->setPixmap(QPixmap(":/th.jpg").scaled(20,20));
    ui->statusBar->addWidget(new QLabel("连接状态"));
    ui->statusBar->addWidget(m_status);
}

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

void MainWindow::on_setlisten_clicked()
{
    unsigned short port = ui->port->text().toUShort();
    //监听
    m_s->listen(QHostAddress::Any,port);
    //设置按钮不可选
    ui->setlisten->setDisabled(true);
}

void MainWindow::on_sendmsg_clicked()
{
    QString msg = ui->msg->toPlainText();
    m_tcp->write(msg.toUtf8());
    ui->record->append("服务端说: "+msg);
}

3.2客户端

客户端与服务器端其实差不多,稍微修改即可如图

image-20230814205518856

3.2.1流程

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

3.2.2代码

头文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

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

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private slots:

    void on_sendmsg_clicked();

    void on_connect_clicked();

    void on_disconnect_clicked();

private:
    Ui::MainWindow *ui;
    QTcpSocket *m_tcp;
    QLabel *m_status;
};

#endif // MAINWINDOW_H

源文件

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

#include <QHostAddress>


MainWindow::MainWindow(QWidget *parent) :
    QMainWindow(parent),
    ui(new Ui::MainWindow)
{
    ui->setupUi(this);
    ui->port->setText("9527");
    ui->ip->setText("127.0.0.1");
    setWindowTitle("客户端");
    ui->disconnect->setDisabled(true);
    //实例化
    m_tcp = new QTcpSocket(this);

    connect(m_tcp,&QTcpSocket::readyRead,this,[=](){
        QByteArray data = m_tcp->readAll();
        ui->record->append("服务端发来:"+data);
    });


    connect(m_tcp,&QTcpSocket::disconnected,this,[=](){
        ui->connect->setDisabled(false);
        ui->disconnect->setEnabled(false);
        m_tcp->close();
        //m_tcp->deleteLater();     //封装后的delete
        m_status->setPixmap(QPixmap(":/th.jpg").scaled(20,20));
        ui->record->append("连接断开.....");
    });

    connect(m_tcp,&QTcpSocket::connected,this,[=](){
        ui->connect->setDisabled(true);
        ui->disconnect->setEnabled(true);
        m_status->setPixmap(QPixmap(":/OIP-C.jpg").scaled(20,20));
        ui->record->append("连接成功.....");
    });


    //状态栏
    m_status = new QLabel;
    m_status->setPixmap(QPixmap(":/th.jpg").scaled(20,20));
    ui->statusBar->addWidget(new QLabel("连接状态"));
    ui->statusBar->addWidget(m_status);
}

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

void MainWindow::on_sendmsg_clicked()
{
    QString msg = ui->msg->toPlainText();
    m_tcp->write(msg.toUtf8());
    ui->record->append("客户端说: "+msg);
}


void MainWindow::on_connect_clicked()
{
    QString ip = ui->ip->text();
    unsigned short port = ui->port->text().toUShort();
    m_tcp->connectToHost(QHostAddress(ip),port);
}

void MainWindow::on_disconnect_clicked()
{
    m_tcp->close();
    ui->connect->setDisabled(true);
    ui->disconnect->setEnabled(false);
}

下面是运行图片

image-20230814205919693

标签:网络通信,QTcpServer,Qt,void,TCP,ui,tcp,QTcpSocket,MainWindow
From: https://www.cnblogs.com/dwinternet/p/17629756.html

相关文章

  • 命令行抓包工具tcpdump
    命令行抓包工具tcpdumptcpdumptcpdump是一个用于截取网络分组,并输出分组内容的工具。tcpdump凭借强大的功能和灵活的截取策略,使其成为类UNIX系统下用于网络分析和问题排查的首选工具。tcpdump提供了源代码,公开了接口,因此具备很强的可扩展性,对于网络维护和入侵者都是非常有用的工具......
  • 一文玩转MQTT (ESP8266 DHT11 MQTT MYSQL方案)
    本文我们来聊一聊esp8266利用mqtt协议进行通信。并将数据数据存入数据库的操作。关于MQTTMQTT(消息队列遥测传输协议),是一种基于发布/订阅(publish/subscribe)模式的“轻量级”通讯协议,MQTT最大优点在于,用极少的代码和有限的带宽,为连接远程设备提供实时可靠的消息服务。搭建MQTT服务器......
  • QT的安装
    qt的安装:  http://download.qt.io/archive/qt/  这是下载的网址,我下载的是5.12.11 需要先注册一个qt的账号才可以进行安装。https://www.qt.io/  这是账号的注册网址。 接下来进行安装。      安装完之后进行简答的测试:     ......
  • 在MQTT通信中用AT指令发送json格式的内容
    在MQTT通信中使用AT指令发送JSON格式的内容,需要使用适用于你的设备的AT指令集,并按照以下步骤进行操作:建立MQTT连接:首先,使用AT指令建立与MQTT代理服务器的连接。这可能涉及到设置服务器地址、端口、用户名、密码等参数。创建JSON数据:在你的设备中,使用AT指令创建要发送的JSON格式的......
  • 【8月摸鱼计划】Air780E|物联网模组|AT命令|MQTT接入|云平台(1)-MQTT基本原理及AT步骤
    基础资料基于Air780E开发板:Air780E文档中心简介:AT开发探讨重点AT固件是通信模组或者单片机(MCU)+网络模块标准固件的基本配置,该模式定制化程序较高,简单易上手,但缺点也较为明显,仅用于快速基本功能验证。本系列主要探讨MQTT方式手动接入、信息订阅及发布的基本原理,后续详细介绍接入多......
  • Qt 之 QWidget QLabel
    @TOC前言一、Qt工程介绍QtCreator以工程项目的方式对源码进行管理一个QtCreator工程包含不同类型的文件。a-.pro.user用户配置描述文件-.h头文件.cpp源文件.ui界面描述文件资源文件(图片,音频,等)pro项目描述文件的基本组成#一注释起始符:以“#”开始,到这一行结束。快捷键:C......
  • 【PYQT5】textEdit滚动条跟踪内容向下
    classMain(QWidget,Ui_Form):def__init__(self):super(Main,self).__init__()self.setupUi(self)self.textEdit.setReadOnly(True)#设置为只读QTimer.singleShot(0,self.thread_check)#延迟执行#textEdit......
  • Linux MQTT智能家居(温度,湿度,环境监测,摄像头等界面布局设置)
    (文章目录)前言本篇文章来完成另外三个界面的布局设置。这里会使用到feiyangqingyun的一些控件库。一、温度湿度曲线布局TempHumtiy.h:#ifndefTEMPHUMTIY_H#defineTEMPHUMTIY_H#include<QWidget>#include"wavechart.h"namespaceUi{classTempHumtiy;}class......
  • 【PYQT5】创建线程,防止执行函数卡死界面
    #线程函数classWorkerThread(QThread):resultReady=pyqtSignal(object)def__init__(self,func,*args,**kwargs):super().__init__()self.func=funcself.args=argsself.kwargs=kwargsdefrun(self):se......
  • Linux上安装Qt Creator
    在Linux系统上安装QtCreator1.在qt官网下载安装包:qt-opensource-linux-x64-5.12.9.run2.wgethttps:://download.qt.io/archive/qt/5.12/5.12.9/qt-opensource-linux-x64-5.12.9.run3.赋予可执行权限,加上sudo权限进入安装,这样会安装在/opt目录下chmod+xqt-opensource-linux-......