Qt中的网络通信

C++没有封装专门的网络套接字的类,因此C++只能调用C对应的API,而在Linux和Windows环境下的API都是不一样的
Qt作为一个C++框架提供了相关封装好的套接字通信类
在Qt中需要用到两个类,两个类都属于network且都是属于IO操作,只不过这两个类是对网络传过来数据进行IO操作
使用前需要再.pro文件里添加 += network
QTcpServer 服务器类,用于监听客户端连接和与客户端创建连接
QTcpSocket 通信的套接字类,服务器和客户端都要使用

QTcpServer常用API

常用函数

构造函数

参数指定父对象,目的是利用Qt对象树机制

QTcpServer::QTcpServer(QObject *parent = 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

注:
1.listen函数的两个参数都有默认值,但是端口号必须由程序员指定,否则系统会随机绑定一个端口,这样就无法连接了。建议使用5000以上的端口

获取通信套接字

此函数会获得通信使用的套接字对象,这个对象是QTcpServer的子对象,当父对象被析构时,子对象也会被析构

QTcpSocket *QTcpServer::nextPendingConnection()

本函数是一个阻塞函数。当启动服务器线程后调用这个函数后就会阻塞服务器并等待客户端连接,直到客户端连接后解除阻塞,但是不推荐使用,建议使用信号

bool QTcpServer::waitForNewConnection(int msec = 0, bool *timedOut = nullptr)
  • 第一个参数设置最大阻塞时间,单位毫秒
  • 第二个参数是个传出参数true为超时解除阻塞,false为非超时解除阻塞

信号

[signal] void QTcpServer::newConnection()

每次有新连接时都会发出newConnection信号

[signal, since 5.0] void QTcpServer::acceptError(QAbstractSocket::SocketError socketError)

当接受新连接导致错误时,会发出acceptError信号,socketError参数描述了错误信息

QTcpSocket常用API

Qt读写网络上传过来的数据,本质上是对本地的数据进行读写,因为Qt会对接收的数据放入一块分配好的内存,然后对这块内存进行读写

常用函数

构造函数

QTcpSocket::QTcpSocket(QObject *parent = nullptr)

连接服务器,指定端口和IP地址等需要的信息
第一个参数是服务器地址(IP地址),第二个参数是服务器端口,服务器绑定了哪个端口就连接哪个端口,第三个参数是打开方式,第四个参数一般不做修改

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

void QAbstractSocket::connectToHost(const QHostAddress &address, quint16 port, QIODeviceBase::OpenMode openMode = ReadWrite)

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

通信流程

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

网络通信发送文件与进度条处理

服务端

子线程文件

#include "recvfile.h"
#include <QFile>

RecvFile::RecvFile(QTcpSocket* tcp,QObject *parent)
    : QThread{parent}
{
    m_tcp = tcp;
}

void RecvFile::run()
{
    QFile *file = new QFile("recv.txt");
    file->open(QFile::WriteOnly);

    //接受数据
    connect(m_tcp,&QTcpSocket::readyRead,this,[=]()
    {
        static int count = 0;
        static int total = 0;
        if (count == 0)
        {
            m_tcp->read((char*)&total,4);
        }
        //读出剩余的数据
        QByteArray all = m_tcp->readAll();
        count += all.size();
        file->write(all);

        if (count == total)
        {
            m_tcp->close();
            m_tcp->deleteLater();
            file->close();
            file->deleteLater();
            emit over();
        }

    });
    //进入事件循环,要一直等有没有文件发过来
    exec();
}

主线程文件

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "recvfile.h"
#include <QMessageBox>
#include <QTcpSocket>
#include <QDebug>

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

    qDebug() << "服务器主线程:" << QThread::currentThread();

    m_s = new QTcpServer(this);
    //有连接的信号槽处理
    connect(m_s,&QTcpServer::newConnection,this,[=](){
        QTcpSocket* m_tcp = m_s->nextPendingConnection();
        //创建子线程对象
        RecvFile* subThread = new RecvFile(m_tcp);
        subThread->start();

        connect(subThread,&RecvFile::over,this,[=](){
            subThread->quit();
            subThread->wait();
            subThread->deleteLater();
            QMessageBox::information(this,"信息","文件传输完毕");
        });
    });
}

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

void MainWindow::on_setListen_clicked()
{
    unsigned short port = ui->port->text().toUShort();
    m_s->listen(QHostAddress::Any,port);
}


客户端

工作类

#include "sendfile.h"
#include <QFile>
#include <QFileInfo>
#include <QHostAddress>

SendFile::SendFile(QObject *parent)
    : QObject{parent}
{}

void SendFile::connectToServer(unsigned short port, QString ip)
{
    m_socket = new QTcpSocket;
    //连接服务器
    m_socket->connectToHost(QHostAddress(ip),port);
    //检测服务器和客户端是否连接成功
    connect(m_socket,&QTcpSocket::connected,this,&SendFile::connetOK);
    //断开连接操作
    connect(m_socket,&QTcpSocket::disconnected,this,[=](){
        m_socket->close();
        m_socket->deleteLater();
        emit fileFinish();
    });

}

void SendFile::sendFile(QString path)
{
    //打开文件
    QFile file(path);

    //第一次发送时要获取文件大小
    QFileInfo info(path);
    //文件大小
    int fileSize = info.size();

    file.open(QFile::ReadOnly);
    //文件没读完就一直读
    while (!file.atEnd())
    {
        //第一次循环就发送文件大小
        static int num = 0;
        if (num == 0)
        {
            m_socket->write((char*)&fileSize,4);
        }
        QByteArray line = file.readLine();
        num += line.size();
        //计算当前的发送百分比
        int percent = num * 100 / fileSize;
        //发送对应用于进度条维护的信号
        emit curPercent(percent);
        //发送信息
        m_socket->write(line);

    }

}

主窗口

#include "mainwindow.h"
#include "ui_mainwindow.h"
#include <QThread>
#include "sendfile.h"
#include <QMessageBox>
#include <QFileDialog>

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

    //初始化端口,ip和进度条
    ui->ip->setText("127.0.0.1");
    ui->port->setText("8989");
    ui->progressBar->setRange(0,100);
    ui->progressBar->setValue(0);

    //创建线程对象
    QThread* t = new QThread;
    //创建任务对象
    SendFile* worker = new SendFile;
    //将任务移动到线程里
    worker->moveToThread(t);

    //发送信号告诉子线程什么时候连接服务器,什么时候发送文件
    connect(this,&MainWindow::startConnect,worker,&SendFile::connectToServer);
    connect(this,&MainWindow::sendFile,worker,&SendFile::sendFile);
    //处理子线程发出来的信号
    connect(worker,&SendFile::connetOK,this,[=](){
        QMessageBox::information(this,"连接服务器","服务器连接成功!");

    });

    //更新进度条处理
    connect(worker,&SendFile::curPercent,ui->progressBar,&QProgressBar::setValue);

    //文件发完了就释放资源
    connect(worker,&SendFile::fileFinish,this,[=](){
        //资源释放
        t->quit();
        t->wait();
        worker->deleteLater();
        t->deleteLater();
    });

    t->start();

}

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

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


void MainWindow::on_selFile_clicked()
{
    QString path = QFileDialog::getOpenFileName();
    if (path.isEmpty())
    {
        QMessageBox::warning(this,"警告","文件路径不能为空!");
        return;
    }
    ui->filePath->setText(path);
}


void MainWindow::on_sendFile_clicked()
{
    emit sendFile(ui->filePath->text());
}


本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:/a/535231.html

如若内容造成侵权/违法违规/事实不符,请联系我们进行投诉反馈qq邮箱809451989@qq.com,一经查实,立即删除!

相关文章

ArcGIS Desktop使用入门(三)图层右键工具——缩放至图层、缩放至可见

系列文章目录 ArcGIS Desktop使用入门&#xff08;一&#xff09;软件初认识 ArcGIS Desktop使用入门&#xff08;二&#xff09;常用工具条——标准工具 ArcGIS Desktop使用入门&#xff08;二&#xff09;常用工具条——编辑器 ArcGIS Desktop使用入门&#xff08;二&#x…

Java 怎么捕捉 Windows 中前台窗口的改变?

在Java中捕捉Windows中前台窗口的改变通常需要使用JNI&#xff08;Java Native Interface&#xff09;来调用Windows API。Windows API提供了一系列函数来获取有关窗口和进程的信息&#xff0c;通过使用这些函数&#xff0c;我们可以实现在Java程序中监视和捕捉Windows前台窗口…

抖音爬虫——点赞量

该爬虫模拟了一个get请求来得到返回json里面的点赞量信息 下面介绍如何使用&#xff1a; 首先&#xff0c;我们找一个浏览器打开抖音搜索具体的关键词 接着我们点击键盘的F12建 就会出现如下的界面&#xff0c;接着我们点击网络&#xff08;可能再一些浏览器是叫network&…

JavaSE:this关键字(代码和内存图讲解)

this的含义 this代表当前对象&#xff0c;谁调用this所在的方法&#xff0c;this就代表谁 这句话非常重要 demo 以这段代码为例&#xff0c;setNum方法内部的this&#xff0c;setStr方法内部的this&#xff0c;还有构造方法ThisKeyword(int num, String str)内部的两个this…

软件库V1.2版本开源-首页UI优化

iAppV3源码&#xff0c;首页的分类更换成了标签布局&#xff0c;各位可以参考学习&#xff0c;界面名称已经中文标注&#xff01; 老版本和现在的版本还是有较大的区别的&#xff0c;建议更新一下&#xff01; 新版本改动界面如下&#xff1a; 1、首页.iyu&#xff1a;分类按…

基于javassm实现的幼儿教育管理系统

开发语言&#xff1a;Java 框架&#xff1a;ssm 技术&#xff1a;JSP JDK版本&#xff1a;JDK1.8 服务器&#xff1a;tomcat7 数据库&#xff1a;mysql 5.7&#xff08;一定要5.7版本&#xff09; 数据库工具&#xff1a;Navicat11 开发软件&#xff1a;eclipse/myeclip…

晶核职业选择:六大角色技能揭秘,成为战斗高手!

在晶核的世界中&#xff0c;每一位玩家都扮演着不同角色&#xff0c;组成多样的团队&#xff0c;共同踏上探索未知的征程。而每个角色都有其独特的技能和特点&#xff0c;下面将为你详细介绍每个角色的技能搭配和操作技巧&#xff0c;让你在战斗中游刃有余&#xff0c;一展自己…

MPT - 原理及应用

前文回顾 Merkle原理及应用Merkle代码实现Patricia原理及应用Patricia代码实现 什么是MPT&#xff08;Merkle Patricia Tree&#xff09;树 MPT树是一种数据结构&#xff0c;用于在以太坊区块链中高效地存储和检索账户状态、交易历史和其他重要数据。MPT树的设计旨在结合Merk…

python之文件操作与管理

1、文件操作 通过open&#xff08;&#xff09;操作&#xff0c;来创建文件对象&#xff0c;下面是open&#xff08;&#xff09;函数语法如下&#xff1a; open&#xff08;file,mode r,buffering -1 , encoding None ,errors None , newline None,closefd True,opener …

分布式向量数据库-安装部署

下载 GitHub - pgvector/pgvector: Open-source vector similarity search for Postgres 源码编译 ##文件解压缩 unzip pgvector-0.6.2.zip ##编译 make && make install 功能验证 #安装扩展CREATE EXTENSION vector;#创建测试表CREATE TABLE items (id bigseri…

互联网需要做安全防护吗?

互联网需要做安全防护&#xff0c;因为网络攻击的风险随时存在。一旦遭受大规模攻击&#xff0c;企业很可能会受到严重影响&#xff0c;甚至会造成巨大的经济损失和品牌声誉受损。因此&#xff0c;建议企业在安全防护方面做好以下几点&#xff1a; 加强网络安全意识教育&#x…

libVLC 视频窗口上叠加透明窗口

很多时候&#xff0c;我们需要在界面上画一些三角形、文字等之类的东西&#xff0c;我们之需要重写paintEvent方法&#xff0c;比如像这样 void Widget::paintEvent(QPaintEvent *event) 以下就是重写的代码。 void Widget::paintEvent(QPaintEvent *event) {//创建QPainte…

【Python系列】将生成的 JSON 数据写入 JSON 文件

&#x1f49d;&#x1f49d;&#x1f49d;欢迎来到我的博客&#xff0c;很高兴能够在这里和您见面&#xff01;希望您在这里可以感受到一份轻松愉快的氛围&#xff0c;不仅可以获得有趣的内容和知识&#xff0c;也可以畅所欲言、分享您的想法和见解。 推荐:kwan 的首页,持续学…

直播带货行业将迎来大地震

关注卢松松&#xff0c;会经常给你分享一些我的经验和观点。 为什么这么多人喊着关闭直播带货?实体经济是到底因为什么萧条的?为什么大街上冷冷清清的?是房租、虚高的价格、还是直播带货引起的? 在4月9日的国务院政策吹风会上&#xff0c;市场监管明确指出&#xff1a; …

Spring Cloud学习笔记:Eureka简介,Eureka简单样例

这是本人学习的总结&#xff0c;主要学习资料如下 - 马士兵教育 [TOC](目录)1、Eureka 1.1、架构 Eureka是SpringCloud Nexflix的核心子模块&#xff0c;其中包含Server和Client。 Server提供服务注册&#xff0c;存储所有可用服务节点。 Client用于简化和Server的通讯复杂…

微信小程序uniapp+vue电力巡线任务故障报修管理系统2q91t

uni-app框架&#xff1a;使用Vue.js开发跨平台应用的前端框架&#xff0c;编写一套代码&#xff0c;可编译到Android、小程序等平台。 前端开发:vue 语言&#xff1a;javapythonnodejsphp均支持 运行软件:idea/eclipse/vscode/pycharm/wamp均支持 框架支持:Ssm/django/flask/t…

JVM修炼之路【10】- 垃圾回收器和垃圾回收算法

垃圾回收算法 我们先简要看一下 四种主要的垃圾回收算法 看到这不禁感慨一下 人家1960年 都搞出GC算法了 太强了 评价标准 既然有这么多算法 那就跟各个牌子的游戏本一样 有个比较&#xff0c;这里我们重点介绍一下 垃圾回收算法的评价标准 这几个标准非常重要是 是后面理解很…

初学SSRF总结

什么是SSRF SSRF是由攻击者构造通过服务端发起请求的安全漏洞。通常情况下&#xff0c;SSRF的攻击对象是外部无法访问的内网&#xff08;因为是由服务端发起的请求所以攻击能够访问到内部系统&#xff09; 由于服务端提供了从其它服务器获取数据的功能&#xff0c;但是有没有…

PlanUML和Mermaid哪个好?

引言 在当今信息化快速发展的时代&#xff0c;数据可视化和图表工具不仅对于程序员&#xff0c;也对于非技术背景的人士至关重要。绘图工具可以帮助我们更好地理解和表达复杂的概念或数据流。PlantUML和Mermaid是两款被广泛使用的绘图语言&#xff0c;它们都能够通过简洁的文本…

mynet开源库

1.介绍 个人实现的c开源网络库&#xff0e; 2.软件架构 1.结构图 2.基于event的自动分发机制 3.多优先级分发队列&#xff0c;延迟分发队列 内部event服务于通知机制的优先级为0&#xff0c;外部event优先级为1&#xff0e; 当集中处理分发的event_callback时&#xff0c…