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());
}

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

如若内容造成侵权/违法违规/事实不符,请联系长河编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

混合云构建-如何通过Site to Site VPN 连接 AWS 和GCP云并建立一个高可用的VPN通信

如果我们的业务环境既有AWS云又有GCP云,那么就需要将他们打通,最经济便捷的方式就是通过Site-to-Site VPN连接AWS和GCP云,你需要在两个云平台上分别配置VPN网关,并建立一个VPN隧道来安全地连接这两个环境,我们下面演示一个高可用场景下的S2S VPN线路构建,采用动态BGP协议…

Innodb架构解析

整体架构 通过《面试官&#xff1a;一条SQL是如何执行的&#xff1f;》我们了解了MySQL架构&#xff0c;下面我们看下Innodb架构。 innodb最早由Innobase Oy公司开发&#xff0c;5.5版本开始是MySQL默认存储引擎&#xff0c;该存储引擎是第一个完整支持ACID事务的MySQL存储引…

git修改本地提交历史邮箱地址

1、Git&#xff08;Git&#xff09; 2、修改Git本地提交历史中的邮箱地址 使用 git rebase 命令进行交互式重置。 具体步骤如下&#xff1a;&#xff08;https://git-scm.com/docs/git-rebase&#xff09; 1、查看提交历史&#xff1a; 使用 git log 命令列出提交历史&#x…

弹簧、质量的bode、nyquist与根轨迹图

在控制系统分析中&#xff0c;Bode图、Nyquist图和根轨迹图都是重要的工具&#xff0c;用于评估和分析系统的性能。这些系统的Nyquist图提供了最大的旋转&#xff0c;即它们在频率变化时表现出最大的相位变化。当Nyquist图完全位于虚轴上时&#xff0c;意味着系统的增益&#x…

【学习】移动端兼容性测试有什么方法及重要性

随着移动互联网的快速发展&#xff0c;移动应用程序已经成为人们日常生活中不可或缺的一部分。然而&#xff0c;由于各种移动设备的硬件和软件差异&#xff0c;移动应用程序的兼容性问题也越来越突出。因此&#xff0c;移动端兼容性测试成为了一个重要的环节&#xff0c;它可以…

猝不及防 CCF-B ICPP 2024投稿延期至4月22日提交摘要 机会来了别错过

会议之眼 快讯 第53届ICPP&#xff08;International Conference on Parallel Processing&#xff09;即国际并行处理会议将于 2024年 8月12日-15日在瑞典哥特兰岛举行&#xff01;ICPP是世界上最古老的连续举办的并行计算计算机科学会议之一。它是学术界、工业界和政府的研究…

1572. 【基础赛】涂色(paint)

1572. 【基础赛】涂色&#xff08;paint&#xff09; (Input: paint.in, Output: paint.out) 时间限制: 2 s 空间限制: 256 MB 具体限制 题目描述 Introl获得了一个N行的杨辉三角&#xff0c;他将每行中值为奇数的位置涂为了黑色。 Chihiro将提出M次询问&#xff0c;在第L…

C语言强制类型转换

目录 王道ppt总结&#xff1a; ​编辑相关博主文章&#xff1a; 王道ppt总结&#xff1a; 相关博主文章&#xff1a;char范围详解&#xff0c;为什么是-128~127,以及int类型范围详解&#xff08;整型数据在内存中的存储&#xff09;_char型和int型数据范围-CSDN博客https://b…

数据分析——数据规范化

数据规范化是数据分析中的一个重要步骤&#xff0c;其目的在于确保数据的一致性和可比性&#xff0c;提高数据质量和分析结果的准确性。以下是一些数据规范化的常见方法和技术&#xff1a; 数据清洗&#xff1a;此步骤主要清除数据中的重复项、空格、格式错误等&#xff0c;确…

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

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

华为海思校园招聘-芯片-数字 IC 方向 题目分享——第九套

华为海思校园招聘-芯片-数字 IC 方向 题目分享(共9套&#xff0c;有答案和解析&#xff0c;答案非官方&#xff0c;未仔细校正&#xff0c;仅供参考&#xff09;——第九套 部分题目分享&#xff0c;完整版获取&#xff08;WX:didadidadidida313&#xff0c;加我备注&#xff…

套接字通信模型

本文内容主要参考《Android图形显示系统》 套接字也就是socket&#xff0c;一般用于网络中两个主机之间应用进程进行通信&#xff0c;在同一个主机也可以使用套接字完成进程之间的通信。 在图形显示系统中&#xff0c;用到套接字进行通信的地方主要有VSync信号的分发以及输入事…

代码随想录算法训练营第五十一天 |309. 买卖股票的最佳时机含冷冻期、714. 买卖股票的最佳时机含手续费

代码随想录算法训练营第五十一天 |309. 买卖股票的最佳时机含冷冻期、714. 买卖股票的最佳时机含手续费 309. 买卖股票的最佳时机含冷冻期题目解法 714. 买卖股票的最佳时机含手续费题目解法 感悟 309. 买卖股票的最佳时机含冷冻期 题目 解法 题解链接 1. class Solution { …

2012年认证杯SPSSPRO杯数学建模A题(第二阶段)蜘蛛网全过程文档及程序

2012年认证杯SPSSPRO杯数学建模 A题 蜘蛛网 原题再现&#xff1a; 第二阶段问题   现在我们假设一个具体的环境。假设有一个凸多边形的区域&#xff0c;蜘蛛准备在这个区域&#xff08;或其一部分&#xff09;上结一张网。   问题一&#xff1a; 在区域的边界上安置有若干…

在keil里用c++编程(1)

做嵌入式开发时&#xff0c;我们对使用c语言写的库有强烈的需求&#xff0c;比如eigen&#xff0c;boost等&#xff0c;但是通常来说&#xff0c;我们的开发是围绕c语言进行的&#xff0c;怎么把c的库文件放在c语言环境下进行编译&#xff0c;就是我们需要面对的问题 1.问题来…

【c++】STl-list使用list模拟实现

主页&#xff1a;醋溜马桶圈-CSDN博客 专栏&#xff1a;c_醋溜马桶圈的博客-CSDN博客 gitee&#xff1a;mnxcc (mnxcc) - Gitee.com 目录 1. list的介绍及使用 1.1 list的介绍 1.2 list的使用 1.2.1 list的构造 1.2.2 list iterator的使用 1.2.3 list capacity 1.2.4 …

Linux下网络编程基础知识--协议

网络基础 这一个课程的笔记 相关文章 协议 Socket编程 高并发服务器实现 线程池 协议 一组规则, 数据传输和数据的解释的规则。 比如说依次发送文件的文件名, 文件的大小, 以及实际的文件, 这样规定发送一个文件的顺序以及发送的每一个部分的格式等可以算是一种协议 型协议 …

【MATLAB源码-第185期】基于matlab的16QAM系统相位偏移估计EOS算法仿真,对比补偿前后的星座图误码率。

操作环境&#xff1a; MATLAB 2022a 1、算法描述 1. 引言 M-QAM调制技术的重要性 现代通信系统追求的是更高的数据传输速率和更有效的频谱利用率。M-QAM调制技术&#xff0c;作为一种高效的调制方案&#xff0c;能够通过在相同的带宽条件下传输更多的数据位来满足这一需求…

二分查找-图文详解,看不懂你来打我。。。

一、查找算法 在计算机科学和算法领域&#xff0c;搜索是一项基本的任务。在海量数据中寻找特定的元素是一项常见的任务&#xff0c;而二分查找&#xff08;Binary Search&#xff09;是一种非常高效的搜索算法&#xff0c;特别适用于有序数组。 二、二分查找 二分查找是一种…

ctf_show笔记篇(web入门---SSRF)

ssrf简介 ssrf产生原理&#xff1a; 服务端存在网络请求功能/函数&#xff0c;例如&#xff1a;file_get_contens()这一类类似于curl这种函数传入的参数用户是可控的没有对用户输入做过滤导致的ssrf漏洞 ssrf利用: 用于探测内网服务以及端口探针存活主机以及开放服务探针是否存…