首页 > 其他分享 >【Qt】网络

【Qt】网络

时间:2024-04-04 19:32:12浏览次数:25  
标签:Widget Qt 网络 socket ui QString 服务器 客户端

目录

一、概述

在Qt中,网络编程使用Qt网络模块来实现。对网络编程的API也进行了重新封装。 提供了一套高级的网络编程接口,可以方便地进行网络通信。

在进行网络编程之前,需要在项目中的.pro文件中添加network 模块. 添加之后要 手动编译一下项目, 使Qt Creator能够加载对应模块的头文件.

Qt中的网络模块就是封装了网络API,可参考网络模块,点此处跳转

二、UDP

Qt中的UDP是指用户数据报协议(User Datagram Protocol),它是一种无连接的传输协议,用于在网络上发送数据。在Qt中,可以使用QUdpSocket类来实现UDP通信。

QUdpSocket类提供了用于创建和管理UDP套接字的方法,可以用于发送和接收UDP数据报。

主要的类有两个. QUdpSocket和QNetworkDatagram
QUdpSocket表示一个UDP的socket文件.

在这里插入图片描述

QNetworkDatagram 表示一个 UDP 数据报
在这里插入图片描述

实例

实现一个简易回显服务器

1.服务器搭建

创建项目,在.pro文件中添加network
在这里插入图片描述

在ui中拖入一个QlistWidget显示服务器收到的请求
在这里插入图片描述

编写代码

#include "widget.h"
#include "ui_widget.h"
#include<QUdpSocket>
#include<QMessageBox>
#include<QNetworkDatagram>

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

    //创建对象 socket在类中声明
    socket = new QUdpSocket(this);
    //设置窗口标题
    this->setWindowTitle("服务器");
    //链接信号槽
    connect(socket,&QUdpSocket::readyRead,this,&Widget::processRequest);
    //绑定端口号
    bool ret = socket->bind(QHostAddress::Any,8080);
    if(!ret)
    {
        QMessageBox::critical(this,"服务器启动错误",socket->errorString());
        return;
    }
}

Widget::~Widget()
{
    delete ui;
}
//请求处理接口
QString Widget::process(const QString &request)
{
    //不做处理
    return request;
}

void Widget::processRequest()
{
    //获取数据报
    const QNetworkDatagram& requestDatagram  =socket->receiveDatagram();
    QString request = requestDatagram.data();
    //根据请求报文,响应
    const QString& response = process(request);
    //响应数据报
    QNetworkDatagram responseDatagram(response.toUtf8(),requestDatagram.senderAddress(),requestDatagram.senderPort());
    socket->writeDatagram(responseDatagram);
    QString log = "["+requestDatagram.senderAddress().toString()+":"+QString::number(requestDatagram.senderPort())
            +"] req: "+ request +",rsp: "+response;
    //将获取到的请求显示到控件中
    ui->listWidget->addItem(log);
}

此时我们实现的是回显服务器,并不对服务器收到的请求做处理,在实际开发中,处理请求是特别核心的

2.客户端搭建
先在客户端的.pro文件中添加network
在ui中拖入三个控件,将三个控件按照合适的布局进行管理
在这里插入图片描述

#include "widget.h"
#include "ui_widget.h"

#include<QUdpSocket>
#include<QNetworkDatagram>

//服务器端地址和端口
const QString SERVER_IP ="127.0.0.1";
const quint16 PORT=8080;

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

    socket = new QUdpSocket(this);
    this->setWindowTitle("客户端");

    //处理服务器返回的数据
    connect(socket,&QUdpSocket::readyRead,this,&Widget::processResponse);
}

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


void Widget::on_pushButton_clicked()
{
    //获取输入框中内容
    const QString& text = ui->lineEdit->text();
    //构造UDP数据报
    QNetworkDatagram requestDatagram(text.toUtf8(),QHostAddress(SERVER_IP),PORT);
    //发送数据
    socket->writeDatagram(requestDatagram);
    //将发送的数据添加到列表框中
    ui->listWidget->addItem("客户端:"+text);
    ui->lineEdit->clear();
}

void Widget::processResponse()
{
    //处理接收到的响应
    const QNetworkDatagram& responseDatagram=socket->receiveDatagram();
    QString response = responseDatagram.data();
    //将服务器回应的数据显示到控件中
    ui->listWidget->addItem("服务器:"+response);
}

注意,我们使用的是本地环回进行客户端与服务器通信

效果

请添加图片描述

三、TCP

在Qt中,可以使用QTcpSocket类和QTcpServer类来实现TCP通信。

QTcpSocket类是用于客户端的TCP套接字类,它允许Qt应用程序通过TCP协议与远程服务器进行通信。它提供了一些用于连接服务器、发送和接收数据的方法和信号。

QTcpServer类是用于服务器端的TCP服务类,它允许Qt应用程序在指定端口上监听并接受传入的TCP连接。一旦有连接建立,QTcpServer会创建一个QTcpSocket对象来处理该连接,并发出newConnection信号。
核心类是两个: QTcpServer 和 QTcpSocket

使用TCP套接字进行通信的一般步骤如下:

  • 创建一个QTcpSocket对象或QTcpServer对象。
  • 设置连接的服务器地址和端口(对于客户端)或指定监听的端口(对于服务器端)。
  • 连接到服务器(对于客户端)或启动服务器(对于服务器端)。
  • 对于客户端,可以使用connectToHost()方法连接到服务器;对于服务器端,可以使用listen()方法开始监听指定的端口。
  • 一旦连接建立或有新的连接到来,会发出相应的信号(例如connected()信号、newConnection()信号)。
  • 通过read()方法读取来自服务器的数据(对于客户端)或通过QTcpSocket对象的read()方法读取来自客户端的数据(对于服务器端)。
  • 可以通过write()或writeData()方法向服务器发送数据(对于客户端)或通过QTcpSocket对象的write()或writeData()方法向客户端发送数据(对于服务器端)。
  • 对于客户端,可以通过close()方法关闭连接或在读写过程中发生错误时自动关闭连接;对于服务器端,可以通过close()方法关闭服务器。
  • 在不需要连接或服务器时,应当释放相应的QTcpSocket对象或QTcpServer对象。

QTcpServer用于监听端口,和获取客户端连接.
在这里插入图片描述
QTcpSocket用户客户端和服务器之间的数据交互.

在这里插入图片描述

QByteArray用于表示一个字节数组.可以很方便的和QString进行相互转换. 例如:
使用QString的构造函数即可把QByteArray转成QString.
使用QString的toUtf8函数即可把QString转成QByteArray.

实例

实现一个回显服务器和客户端

客户端与服务器界面搭建和UDP回显服务器一致,只是使用不同的步骤实现通信

服务器

通过信号方式处理连接,通过信号的方式处理断开连接,以及读取数据

#include "widget.h"
#include "ui_widget.h"

#include<QMessageBox>
#include<QTcpSocket>

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

    //修改窗口标题
    this->setWindowTitle("服务器");
    tcpServer = new QTcpServer(this);
    //通过信号槽,处理连接
    connect(tcpServer,&QTcpServer::newConnection,this,&Widget::processConnecton);
    //绑定并监听端口号
    bool ret = tcpServer->listen(QHostAddress::Any,8080);
    if(!ret)
    {
        QMessageBox::critical(this,"服务器启动失败",tcpServer->errorString());
        exit(1);
    }
}

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

QString Widget::process(const QString &request)
{
    return request;
}

void Widget::processConnecton()
{
    //通过tcpServer拿到socket对象,进行与客户端通信
    QTcpSocket* clientsocket = tcpServer->nextPendingConnection();
    QString log = "["+clientsocket->peerAddress().toString()+":"+QString::number(clientsocket->peerPort())+"]客户端上线";
    ui->listWidget->addItem(log);

    //通过信号槽,处理客户端请求
    connect(clientsocket,&QTcpSocket::readyRead,this,[=](){
        //读取请求数据
        QString request = clientsocket->readAll();
        //根据请求处理响应
        const QString& response = process(request);
        clientsocket->write(response.toUtf8());
        QString log ="["+clientsocket->peerAddress().toString()+": "+QString::number(clientsocket->peerPort())+"]"
                +"req:"+request+",resp:"+response;
        ui->listWidget->addItem(log);
    });

    //处理断开连接
    connect(clientsocket,&QTcpSocket::disconnected,this,[=](){
        //打印日志
        QString log = "["+clientsocket->peerAddress().toString()+":"+QString::number(clientsocket->peerPort())+"]客户端下线";
        ui->listWidget->addItem(log);
        //手动释放clientSocket 每个客户端有一个clientSocke,如果客户端连接过多,
        //不会立即释放,
        clientsocket->deleteLater();
    });
}

客户端

#include "widget.h"
#include "ui_widget.h"
#include<QMessageBox>
#include<QListWidget>

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

    //设置窗口标题
    this->setWindowTitle("客户端");
    //创建socket
    socket = new QTcpSocket(this);
    //和服务器建立连接
    socket->connectToHost("127.0.0.1",8080);
    //处理响应
    connect(socket,&QTcpSocket::readyRead,this,[=](){
        QString response = socket->readAll();
        ui->listWidget->addItem("服务器:"+response);
    });
    //等待连接结果
    bool ret =socket->waitForConnected();
    if(!ret)
    {
        QMessageBox::critical(this,"连接服务器出错",socket->errorString());
        exit(1);
    }



}

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


void Widget::on_pushButton_clicked()
{
    //获取输入框中内容
    const QString& text = ui->lineEdit->text();
    //发送数据给服务器
    socket->write(text.toUtf8());
    //消息显示到界面
    ui->listWidget->addItem("客户端:"+text);
    ui->lineEdit->clear();
}

实现效果

请添加图片描述

四、HTTP

关键类主要是三个. QNetworkAccessManager,QNetworkRequest,QNe tworkReply

QNetworkAccessManager:

  • 这是所有网络请求的核心管理器,负责处理HTTP、FTP等各种网络请求。
    应用程序通常只需要创建一个QNetworkAccessManager实例,就可以处理所有的网络事务。
    QNetworkRequest:

  • 这个类用于封装HTTP请求的细节,包括URL、HTTP头部信息(如Cookie、认证信息等)、请求方法(GET、POST等)等。

QNetworkReply:

  • 当发出HTTP请求后,QNetworkAccessManager会返回一个QNetworkReply对象,它代表了HTTP响应。
  • 通过信号槽机制,可以从QNetworkReply对象获取到服务器的响应数据、状态码、响应头等信息。

QNetworkReply

  • 通常是异步工作的,这意味着发出请求后不会阻塞线程,而是在响应数据可用或请求完成时触发相应的信号。

QNetworkAccessManager提供了HTTP的核心操作
在这里插入图片描述
QNetworkRequest表示一个 HTTP请求(不含body).

如果需要发送一个带有body的请求(此如post),会在QNetworkAccessManager的post方法中通过单独的参数来传入body.
在这里插入图片描述
其中的QNetworkRequest: : KnownHeaders是一个枚举类型,常用取值:
在这里插入图片描述
在这里插入图片描述
QNetworkReply表示一个HTTP响应.这个类同时也是QIODevice的子类

在这里插入图片描述
QNetworkReply 还有一个重 要的信号finished 会在客户端收到完整的响应数据之后触发.

实例

简单搭建一个Http客户端
在ui中拖入一些控件

在这里插入图片描述

#include "widget.h"
#include "ui_widget.h"
#include<QNetworkReply>

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

    this->setWindowTitle("客户端");
    //manager在.h中声明
    manager= new QNetworkAccessManager(this);
}

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


void Widget::on_pushButton_clicked()
{
    //获取输入框数据
    QUrl url(ui->lineEdit->text());
    //构造一个Http请求
    QNetworkRequest request(url);
    //发送请求
    QNetworkReply* response = manager->get(request);
    //通过信号槽处理响应
    connect(response,&QNetworkReply::finished,this,[=](){
       if(response->error()==QNetworkReply::NoError)
       {
           //正确获取响应
           QString html =response->readAll();
           ui->plainTextEdit->setPlainText(html);
       }else
       {
           //响应出错
           ui->plainTextEdit->setPlainText(response->errorString());
       }
       //对response释放
       response->deleteLater();
    });
}

实现效果

这里选用Plain Text Edit作为显示控件,是因为它是一个纯文本显示,不会对获取的html格式内容进行渲染,在输入框中输入要请求地址,点击按钮,则可以获取到响应信息

在这里插入图片描述

标签:Widget,Qt,网络,socket,ui,QString,服务器,客户端
From: https://blog.csdn.net/Tianzhenchuan/article/details/137268139

相关文章

  • 【Linux】网络基础常识
    文章目录1.网络常识1.0dhcp协议1.1ip地址,mac地址是什么?1.2你拿着手机是如何连接上wifi的?1.3数据,流量是什么?手机如何通过“数据/流量”上网?1.4电脑连接wifi的原理?电脑通过热点上网的原理?1.5固定电话打电话的原理?智能手机打手机电话/语音电话/视频电话的原理?1.62g,5g有什......
  • Qt自定义控件之Battery电池控件
    文章目录前言一、BasicBattery二、Battery控件三、效果总结前言在Qt应用程序开发中,自定义控件是一种常见的需求,开发者经常需要根据特定的需求创建定制化的控件来增强用户界面的交互性和美观性。Battery电池控件是一种常见的自定义控件,用于显示设备的电池状态。通过B......
  • 软考中级(网络工程师考核要点)第一章 计算机网络系统(信道特性应用)第九期(海明码和CRC
    第八期的题目分析:1.分析:D。光纤通信的使用是波分复用,T1/E1是同步时分复用,因为它们使用固定的时钟来确定数据的传输速率。同时,T1/E1也支持异步传输,但通常以同步方式使用。WIFI是异步时分复用,因为它使用无线信号传输数据,没有严格的时钟同步要求。WIFI的数据传输速率可以根据......
  • 第一章 计算机网络体系结构
    一、计算机网络概述        1)概念        计算机网络:将分散的、具有独立功能的计算机系统,通过通信设备与线路连接起来,由功能完善的软件实现资源共享和信息传递的一个系统。互连的(通过通信链路互联互通的)、自治的(无主从关系)计算机集合     ......
  • 【QT教程】QT6与WebEngine
    主页  软件开发  QT6编程基础补天云火鸟自动化创作平台您能够创建大约3000个短视频一天可以轻松创建多达100个视频QT6与WebEngine使用AI技术辅助生成【QT免费公开课】您可以到这里观看大量的QT视频课程【QT付费视频课程】如何使用QtWebEngine开发一款Web浏览......
  • QT基础(B站自学笔记)
    1.程序运行原理#include"mainwindow.h"#include<QApplication>intmain(intargc,char*argv[]){QApplicationa(argc,argv);MainWindoww;//创建窗口对象ww.show();//显示窗口returna.exec();//进入事件循环}2.QOBJECT宏#ifndef......
  • QT创建工程
    step1:step2:step3:step4:step5:出现了文件显示不全的问题:解决方法:......
  • Qt C++ | Qt 元对象系统、信号和槽及事件(第一集)
    01元对象系统一、元对象系统基本概念1、Qt的元对象系统提供的功能有:对象间通信的信号和槽机制、运行时类型信息和动态属性系统等。2、元对象系统是Qt对原有的C++进行的一些扩展,主要是为实现信号和槽机制而引入的,信号和槽机制是Qt的核心特征。3、要使用元对象系统......
  • Qt | 发布程序(以 minGW 编译器为例)
    1、注意:修改pro文件后,最好执行“构建”>“重新构建项目”,否则pro文件的更改将不会反应到程序上。2、发布程序的目的:就是让编译后生成的可执行文件(如exe文件),能在其他计算机上运行。一、编译后生成的各种文件简介QtCreator 构建项目后产生的文件及目录见下图......
  • 超强来袭 基于卷积神经网络结合双向长短记忆网络CNN-BiLSTM实现风电功率多输入单输出
     ✅作者简介:热爱科研的Matlab仿真开发者,修心和技术同步精进,代码获取、论文复现及科研仿真合作可私信。......