QT学习之旅 - network连接

news/2024/7/24 8:35:56 标签: qt, 学习, 开发语言

文章目录

      • 网络知识点
        • IP地址
          • IPv4和IPv6
        • 端口号(协议端口)
          • 端口分类
          • UDP端口和TCP端口
      • network
        • pro文件
        • .h文件
        • .cpp文件
      • UDP连接
        • 绑定端口
        • 绑定成功后等待对方进行连接
        • 点击发送
        • 源码
        • 扩展: nodejs-udp服务端(用于跟QT程序进行通信)
        • 现象

网络知识点

IP地址

192.168.127.170(√)
192.168.330.170(×)

IP地址的范围在0~255

IPv4和IPv6

IPv4:32位(4个字节)
IPv6: 128位(16个字节)。新技术是漫游IP(就是多个局域网进行切换的时候,保持同一个IP地址不变),IPv6解决了IPv4面临枯竭的问题
v4和v6都是IP的版本的意思

端口号(协议端口)

16位(2个字节 short 1~65535)

端口分类
  • 通用端口: 1~1023(一般由系统来维护)
  • 注册端口: 1024~49151(应用,开发者来申请,建议使用5000以上端口号)
  • 临时端口: 49152~65535(通用和注册端口号都是给服务端的,这个临时端口号是给客户端的)
UDP端口和TCP端口

network

pro文件

QT       += network

我写在了``中

.h文件

#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <timeclock.h>
#include <QtNetwork>
#include <QNetworkRequest>
#include <QNetworkReply>
#include <QNetworkAccessManager>

namespace Ui {
class MainWindow;
}

class MainWindow : public QMainWindow
{
    Q_OBJECT

public:
    explicit MainWindow(QWidget *parent = 0);
    ~MainWindow();
private:
    QUrl url;
    QNetworkRequest req;
    QNetworkReply *reply;
    QNetworkAccessManager *manager;
private:
    Ui::MainWindow *ui;
    void startRequest(const QUrl &requestedUrl);
    void replyFinished();
};

#endif // MAINWINDOW_H

.cpp文件

void MainWindow::startRequest(const QUrl &requestedUrl){
    url = requestedUrl;
    manager = new QNetworkAccessManager(this);
    req.setUrl(url);
    req.setRawHeader("Accept","text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.9");
    req.setRawHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/86.0.4240.198 Safari/537.36");
    reply = manager->get(req);
    connect(reply,&QNetworkReply::finished,this,&MainWindow::replyFinished);
}

void MainWindow::replyFinished(){

    // <1>判断有没有错误
    if (reply->error()){
        qDebug()<<reply->errorString();
        reply->deleteLater();
        return;
    }

    // <2>检测状态码
    int statusCode  = reply->attribute(QNetworkRequest::HttpStatusCodeAttribute).toInt();
    qDebug() << "statusCode:" << statusCode;

    // <3>判断是否需要重定向
    if (statusCode >= 200 && statusCode <300){
        // ok

        // 准备读数据
        QTextCodec *codec = QTextCodec::codecForName("utf8");
        QString all = codec->toUnicode(reply->readAll());
        qDebug() << all;


        // 保存HTTP响应内容
        // 组装保存的文件名 文件名格式: 路径/年_月_日 小时_分_秒 httpfile.html
        QDateTime current_date_time =QDateTime::currentDateTime();
        QString current_date =current_date_time.toString("yyyy_MM_dd hh_mm_ss");
        QString filePath = "D:/Qt/QTtest/qt4/myHTTP/doc";
        QString fileName = filePath + '/' + current_date + " httpfile" + ".html";

        QFile file(fileName);
        if (!file.open(QIODevice::ReadWrite | QIODevice::Text)){
            qDebug() << "file open error!";
            return ;
        }
        QTextStream out(&file);
        out.setCodec("UTF-8");
        out<<all << endl;
        file.close();


        // 数据读取完成之后,清除reply
        reply->deleteLater();
        reply = nullptr;

    } else if (statusCode >=300 && statusCode <400){
        // redirect

        // 获取重定向信息
        const QVariant redirectionTarget = reply->attribute(QNetworkRequest::RedirectionTargetAttribute);
        // 检测是否需要重定向,如果不需要则读数据
        if (!redirectionTarget.isNull()) {
            const QUrl redirectedUrl = url.resolved(redirectionTarget.toUrl());

            reply->deleteLater();
            reply = nullptr;

            startRequest(redirectedUrl);
            qDebug()<< "http redirect to " << redirectedUrl.toString();
            return;
        }


    }

}

设置连接的URL

startRequest(QUrl(link));

UDP连接

在这里插入图片描述

绑定端口

udpSocket = new QUdpSocket(this);

/*
bind:绑定端口
QHostAddress::Any : 本机下所有的端口
udpSocket->bind(address,port);
*/
udpSocket->bind(QHostAddress::Any,9000);

绑定成功后等待对方进行连接

connect(udpSocket,&QUdpSocket::readyRead,this,&MainWindow::dealMsg);

在这里插入图片描述

void MainWindow::dealMsg(){
    //接收信息
    char buf[1024] = {0};
    QHostAddress ip;
    quint16 port;
    //readDatagram(数据缓存地址,缓存的数据大小,对方ip,对方端口)
    quint16 len = udpSocket->readDatagram(buf,sizeof(buf),&ip,&port);
    if(len > 0){
        //说明有接收,小于0是出错
        //显示
        QString str = QString("[%1:%2] %3")
                .arg(ip.toString())
                .arg(port)
                .arg(buf);

        ui->textEdit->append(str);
    }
}

点击发送

void MainWindow::on_buttonSend_clicked(){
  if(ui->lineEditIP == nullptr|| ui->lineEditPort == nullptr){
    return;
  }
  QString ip = ui->lineEditIP->text();
  quint16 port = ui->lineEditPort->text().toInt();
  //读取编辑区内容
  if(ui->textEditWrite == nullptr){
      return;
  }
  QString str = ui->textEditWrite->toPlainText();
  //写入套接字
  udpSocket->writeDatagram(str.toUtf8(),QHostAddress(ip),port);
  qDebug() << "send ip:" << ip;
  qDebug() << "send port:" << port;

}

源码

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QDebug>

MainWindow::MainWindow(QWidget *parent)
    : QMainWindow(parent)
    , ui(new Ui::MainWindow)
{

    ui->setupUi(this);
    ui->textEdit->setReadOnly(true);//设置为只读
    
    setWindowTitle("端口号:9000");
    udpSocket = new QUdpSocket(this);

    /*
    bind:绑定端口
    QHostAddress::Any : 本机下所有的端口
    udpSocket->bind(address,port);
    */
    udpSocket->bind(QHostAddress::Any,9000);

    connect(udpSocket,&QUdpSocket::readyRead,this,&MainWindow::dealMsg);
    connect(ui->send,&QPushButton::clicked,this,&MainWindow::on_buttonSend_clicked);
}

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

void MainWindow::dealMsg(){
    //接收信息
    char buf[1024] = {0};
    QHostAddress ip;
    quint16 port;
    //readDatagram(数据缓存地址,缓存的数据大小,对方ip,对方端口)
    quint16 len = udpSocket->readDatagram(buf,sizeof(buf),&ip,&port);
    if(len > 0){
        //说明有接收,小于0是出错
        //显示
        QString str = QString("[%1:%2] %3")
                .arg(ip.toString())
                .arg(port)
                .arg(buf);

        qDebug() << "ip:" << ip;
        qDebug() << "port:" << port;

        ui->textEdit->append(str);
    }
}

void MainWindow::on_buttonSend_clicked(){
  if(ui->lineEditIP == nullptr|| ui->lineEditPort == nullptr){
    return;
  }
  QString ip = ui->lineEditIP->text();
  quint16 port = ui->lineEditPort->text().toInt();
  //读取编辑区内容
  if(ui->textEditWrite == nullptr){
      return;
  }
  QString str = ui->textEditWrite->toPlainText();
  //写入套接字
  udpSocket->writeDatagram(str.toUtf8(),QHostAddress(ip),port);
  qDebug() << "send ip:" << ip;
  qDebug() << "send port:" << port;

}

void MainWindow::on_buttonClose_clicked(){

}
#ifndef MAINWINDOW_H
#define MAINWINDOW_H

#include <QMainWindow>
#include <QUdpSocket>
#include <QHostAddress>
#include <QLabel>
#include <QPushButton>

QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACE

class MainWindow : public QMainWindow
{
    Q_OBJECT

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

private:
    Ui::MainWindow *ui;
    QUdpSocket *udpSocket;
    void on_buttonSend_clicked();
    void on_buttonClose_clicked();
private slots:
    void dealMsg();
};
#endif // MAINWINDOW_H

在这里插入图片描述

扩展: nodejs-udp服务端(用于跟QT程序进行通信)

npm i express
//服务端
const dgram = require('dgram');
//创建udp server
let udp_server = dgram.createSocket('udp4');
udp_server.bind(5678);//绑定端口

//监听端口
udp_server.on('listening',function(){
    console.log('udp server linstening 5678.');
})

//接收消息
udp_server.on('message', function (msg, rinfo) {
    strmsg = msg.toString();
    udp_server.send(strmsg, 0, strmsg.length, rinfo.port, rinfo.address); //将接收到的消息返回给客户端
    console.log(`udp server received data: ${strmsg} from ${rinfo.address}:${rinfo.port}`)
})
//错误处理
udp_server.on('error', function (err) {
    console.log('some error on udp server.')
    udp_server.close();
})

//客户端
/* var dgram = require('dgram');
var udp_client = dgram.createSocket('udp4'); 

udp_client.on('close',function(){
    console.log('udp client closed.')
})

//错误处理
udp_client.on('error', function () {
    console.log('some error on udp client.')
})

// 接收消息
udp_client.on('message', function (msg,rinfo) {
    console.log(`receive message from ${rinfo.address}:${rinfo.port}:${msg}`);
})

//定时向服务器发送消息
setInterval(function(){
    var SendBuff = 'hello 123.';
    var SendLen = SendBuff.length;
    udp_client.send(SendBuff, 0, SendLen, 5678, '172.30.20.10'); 
},3000); */
npm run start

现象

在这里插入图片描述
在这里插入图片描述


http://www.niftyadmin.cn/n/456535.html

相关文章

侯捷——1.C++面向对象高级开发 总结

侯捷——1.C面向对象高级开发 总结 前面的几个视频没有总结&#xff0c;等以后有空再补 7. Class with pointer member(s) —— string 类 该string类&#xff0c;内含指针&#xff0c;所以要自己写构造函数和析构函数&#xff0c;不能使用默认的构造函数和析构函数。 包含…

Codeforces Round 877 (Div. 2) A~D

Codeforces Round 877 (Div. 2) A. Blackboard List 题意&#xff1a;给两个数&#xff0c;两个差的绝对值为新数&#xff0c;现给出最后的结果&#xff0c;问一开始的两个数的其中一个为什么。 思路&#xff1a;首先负数无法通过绝对值得出&#xff0c;因此如果有负数就选负…

Doris-简介、架构、编译、安装和数据表的基本使用

目录 1、Doris简介2、Doris网址3、Doris架构3、编译和安装 3.1、软硬件需求3.2、编译 3.2.1、安装Docker环境3.2.2、使用Docker 开发镜像编译3.3、集群部署 3.3.1、创建目录并拷贝编译后的文件3.3.2、部署 FE 节点3.3.3、配置 BE 节点3.3.4、在 FE 中添加所有 BE 节点3.3.5、启…

Elasticsearch 分词器

前奏 es的chinese、english、standard等分词器对中文分词十分不友好&#xff0c;几乎都是逐字分词&#xff0c;对英文分词比较友好。 在kibana的dev tools中测试分词&#xff1a; POST /_analyze {"analyzer": "standard","text": "你太…

Debian12中Grub2识别Windows

背景介绍&#xff1a;windows10 debian11,2023年6月&#xff0c;Debian 12正式版发布了。抵不住Debian12新特性的诱惑&#xff0c;我将Debian11升级至Debian12。升级成功&#xff0c;但Debian12的Grub2无法识别Window10。于是执行如下命令&#xff1a; debian:~# update-grub G…

【Python】异常处理try+except和断言assert

原文作者&#xff1a;我辈李想 版权声明&#xff1a;文章原创&#xff0c;转载时请务必加上原文超链接、作者信息和本声明。 文章目录 前言一、常见用法二、内置异常类三、else和finally四、自定义异常1.异常类2.抛出异常 五、断言assert 前言 在 Python 中&#xff0c;异常是…

硬盘被写保护怎么解决

目录 问题描述方法1&#xff1a;使用diskpart清除只读属性方法2&#xff1a;树莓派镜像烧录软件 U盘格式化不了&#xff0c;怎么做呢&#xff1f; 问题描述 方法1&#xff1a;使用diskpart清除只读属性 我是I盘出现了问题&#xff0c;所以我在命令提示符输入&#xff1a; chk…

ESP32设备驱动-TCA9548A-I2C多路复用器驱动

TCA9548A-I2C 多路复用器驱动 文章目录 TCA9548A-I2C 多路复用器驱动1、TCA9548A介绍2、硬件准备3、软件准备4、驱动实现4.1 TCA9548A总线复用实现4.2 驱动多个OLED显示屏4.3 驱动多个BME280传感器在本文中,将介绍如何使用 TCA9458A I2C 多路复用器扩展 I2C 总线端口。 如果你…