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

【QT】Qt网络

在这里插入图片描述
个人主页~


Qt系统相关

  • 一、Qt网络
    • 1、UDP Socket
      • (1)核心API
        • QNetworkDatagram
      • (2)回显服务器
        • widget.cpp
      • (3)回显客户端
        • widget.cpp
    • 2、TCP Socket
      • (1)核心API
        • QTcpServer
        • QTcpSocket
      • (2)回显服务器
      • (3)回显客户端
    • 3、HTTP Client
        • QNetworkAccessManager
        • QNetworkRequest
        • QNetworkReply

一、Qt网络

在这里插入图片描述

在进行网络编程之前,需要在项目中的.pro文件中添加network模块

实际开发中不会用Qt直接写服务器的,因为服务器是没有图形化界面的,一般我们会用其他的语言软件写好程序之后与Qt联合使用,这里只是演示

在实现网络编程的时候在pro文件中要加入network
在这里插入图片描述

1、UDP Socket

(1)核心API

方法说明
bind(const QHostAddress&,quint16)绑定指定的端口号
receiveDatagram返回QNetworkDatagram,读取一个UDP数据报
writeDatagram(const QNetworkDatagram&)发送一个UDP数据报
信号说明
readyRead在收到数据并准备就绪后触发
QNetworkDatagram
构造函数说明
QNetworkDatagram(const QByteArray& ,const QHostAddress& ,quint16)通过QByteArray,目标IP地址,目标端口号构造一个UDP数据报
方法说明
data获取数据报内部持有的数据,返回QByteArray
senderAddress获取数据报中包含的对端的IP地址
senderPort获取数据报中包含的对端的端口号

(2)回显服务器

回显服务器和回显客户端顾名思义就是我给服务器发送什么服务器给我发送什么

widget.cpp
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);
	//修改窗口标题
    this->setWindowTitle("服务器");
    //创建udp实例
    socket = new QUdpSocket(this);
    //连接信号槽
    connect(socket,&QUdpSocket::readyRead,this,&Widget::processRequest);
    //绑定端口
    bool ret = socket->bind(QHostAddress::Any,9090);
    if(!ret)
    {
        QMessageBox::critical(nullptr,"服务器启动有误",socket->errorString());
        return;
    }
}

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+",resp:"+response;
    ui->listWidget->addItem(log);
}

QString Widget::process(const QString &request)
{
	//对于回显服务器来说,请求就是回应,但是对于大型的商务服务器,这里的代码量是非常巨大的
    return request;
}

(3)回显客户端

widget.cpp
const QString& SERVER_IP = "127.0.0.1";//客户端IP地址
const quint16 SERVER_PORT = 9090;//客户端端口号

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);
}
//这个函数用来处理收到的响应
void Widget::processResponse()
{
	//读取解析响应
    const QNetworkDatagram& responseDatagram = socket->receiveDatagram();
    QString response = responseDatagram.data();
    //因为是回显服务器,直接将响应数据显示到界面上
    ui->listWidget->addItem("服务器:"+response);
}


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

qudpsocket

2、TCP Socket

(1)核心API

主要有两个核心类

QTcpServer
方法说明
listen(const QHostAddress&,quint16 port)绑定指定的地址和端口号,并开始监听
nextPendingConnection从系统中获取到一个已经建立好的tcp连接,返回一个QTcpSocket,表示这个客户端的连接,通过这个socket对象完成和客户端之间的通信
信号说明
newConnection有新的客户端建立好之后触发
QTcpSocket
方法说明
readAll读取当前接收缓冲区中的所有数据并返回一个QByteArray对象
write(const QByteArray&)把数据写入socket中
deleteLater暂时把socket对象标记为无效,Qt会在下个事件循环中析构释放该对象
信号说明
readyRead有数据到达准备就绪时触发
disconnected断开连接时触发

(2)回显服务器

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

    // 1. 修改窗口标题.
    this->setWindowTitle("服务器");

    // 2. 创建 QTcpServer 的实例
    tcpServer = new QTcpServer(this);

    // 3. 通过信号槽, 指定如何处理连接.
    connect(tcpServer, &QTcpServer::newConnection, this, &Widget::processConnection);

    // 4. 绑定并监听端口号. 一定要确保准备工作充分了, 再真正开张营业.
    //    这个操作得是初始化的最后一步. 都是需要把如何处理连接, 如何处理请求... 都准备好之后, 才能真正绑定端口并监听.
    bool ret = tcpServer->listen(QHostAddress::Any, 9090);
    if (!ret) {
        QMessageBox::critical(this, "服务器启动失败!", tcpServer->errorString());
        exit(1);
    }
}

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

void Widget::processConnection()
{
    //通过tcpServer获得socket对象, 通过这个对象来和客户端进行通信
    QTcpSocket* clientSocket = tcpServer->nextPendingConnection();
    QString log = "[" + clientSocket->peerAddress().toString() + ":" + QString::number(clientSocket->peerPort()) + "] 客户端上线!";
    ui->listWidget->addItem(log);

    //通过信号槽, 来处理客户端发来请求的情况
    connect(clientSocket, &QTcpSocket::readyRead, this, [=]() {
        //读取出请求数据. 此处 readAll 返回的是 QByteArray, 通过赋值转成 QString
        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. 使用deleteLater更加合适
        clientSocket->deleteLater();
    });
}

//回显服务器.
QString Widget::process(const QString request)
{
    return request;
}

(3)回显客户端

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", 9090);
    //连接信号槽, 处理响应
    connect(socket, &QTcpSocket::readyRead, [=]() {
        // 读取出响应内容
        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->setText("");
}

qtcpsocket

3、HTTP Client

QNetworkAccessManager

提供核心操作

方法说明
get(const QNetworkRequest& )发起一个HTTP GET请求,返回QNetworkReply对象
post(const QNetworkRequest& ,const QByteArray& )发起一个HTTP POST请求,返回QNetworkReply对象
QNetworkRequest

表示一个HTTP请求,不含body,body是数据本体

方法说明
QNetworkRequest(const QUrl& )通过URL构造一个HTTP请求
setHeader(QNetworkRequest::KnowHeaders header,const QVariant& value)设置请求头
QNetworkReply
方法说明
error获取出错状态
errorString获取出错原因的文本
readAll读取响应body
header(QNetworkRequest::KnownHeaders header)读取相应指定header的值
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    manager = new QNetworkAccessManager(this);
}

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


void Widget::on_pushButton_clicked()
{
    //获取到输⼊框中的URL, 构造QUrl对象
    QUrl url(ui->lineEdit->text());
    //构造HTTP请求对象
    QNetworkRequest request(url);
    //发送GET请求
    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->deleteLater();
    });
}

qhttp


今日分享就到这里了~

在这里插入图片描述


http://www.kler.cn/a/389777.html

相关文章:

  • 3D绘制动态爱心Matlab
  • 每日一练:二分查找-搜索插入位置
  • 01-Ajax入门与axios使用、URL知识
  • 使用kalibr_calibration标定相机(realsense)和imu(h7min)
  • SciPy:Python 科学计算工具包的全面教程
  • 【JAVA】正则表达式中的中括弧
  • 【CSS】什么是BFC?
  • 2.5_XXE(XML外部实体注入)
  • 杨辉三角-一维数组与二维数组解法
  • 图片搜索引擎,来快速实现一个高性能的本地图片搜索引擎
  • Ansys EMC Plus:以 Touchstone 格式计算和导出 S 参数
  • Web3推动社交媒体的去中心化转型:挑战与机遇
  • FFmpeg —— 通过AES-CTR方式对视频加密解密(详细介绍通过FFmpeg指令、代码方式进行加密解码,附源码)
  • Information Server 中共享开源服务中 kafka 的__consumer_offsets目录过大清理
  • 第二周训练
  • 计算机网络系列课程《网络解释》
  • 【力扣】05最长的回文子串
  • 【C++ 算法进阶】算法提升十四
  • Python之魔术方法笔记
  • Spring Boot集成SQL Server快速入门Demo
  • jsmind 思维导出 vue 示例
  • ArcGIS从Excel表格文件导入XY数据并定义坐标系与投影的方法
  • Rancher的安装
  • JS禁用鼠标滚动条功能且滚动条不消失教程
  • 使用NVIDIA GPU加速FFmpeg视频压制:完全指南
  • thinkphp自定义命令行+宝塔面板Shell脚本实现定时任务