QT中的服务器与客户端

一、前言

        本文主要讲讲QT中服务器与客户端的使用方法,QT已经封装好了,调用相应类直接访问即可。本文以QT中的QT中的TCP为例子,讲下使用方法以及线程中使用。

二、正文

2.1 Sever的使用方法

2.1.1 思路

QT中Sever使用的时候大致步骤为:

1、创建监听的服务器对象

2、监听到数据信号,创建QTcpSocket的套接字对象

3、检测是否可以接收数据

4、信息发送,查看数据发送是否正常

总的来说,就是先确定要监听的地址与端口,然后数据在套接字中,套接字在QT中是QTcpSocket

封装的类,直接用就行,最后通过套接字接收数据或者发送数据即可。

2.1.2 代码示例

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;QTcpServer *m_server;QTcpSocket *m_tcp;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);ui->lineEdit_port->setText("8888");//创建监听的服务器对象m_server = new QTcpServer(this);connect(ui->pushButton_listen, &QPushButton::clicked, this, [=](){m_server->listen(QHostAddress::Any, ui->lineEdit_port->text().toInt());ui->pushButton_listen->setDisabled(true);});//监听到数据信号,创建QTcpSocket的套接字对象connect(m_server, &QTcpServer::newConnection, this, [=](){m_tcp = m_server->nextPendingConnection();//检测是否可以接收数据connect(m_tcp, &QTcpSocket::readyRead, this, [=](){QByteArray data = m_tcp->readAll();ui->textEdit_historymsg->append("客户端说: " + data);});});//信息发送connect(ui->pushButton_send, &QPushButton::clicked, this, [=](){QString msg = ui->textEdit_sendmsg->toPlainText();m_tcp->write(msg.toUtf8());ui->textEdit_historymsg->append("服务器说: " + msg);});}Widget::~Widget()
{delete ui;
}

2.1.3 细节讲解

创建服务器对象QTcpServer,对象有监听的方法listen。

监听的地址设置所有即可访问你电脑可以收到的所有地址,可以用win+R进入cmd查看有哪些,比如:

获取到新的连接后,将下一个挂起的连接作为已连接的QTcpSocket对象返回

准备读取信号有了后即可开始读取套接字内的数据。

2.1.4 演示

监听成功

2.2 Client的使用方法

2.2.1 思路

QT中Client使用的时候大致步骤为:

1、创建Socket对象,连接服务器

2、数据交互

3、根据需求断开连接

总体来说很简单,套接字连接好服务器的地址与端口即可,前提是服务器开启了,不然连接会失败。

2.2.2 代码示例

#ifndef WIDGET_H
#define WIDGET_H#include <QWidget>
#include <QTcpSocket>QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACEclass Widget : public QWidget
{Q_OBJECTpublic:Widget(QWidget *parent = nullptr);~Widget();private:Ui::Widget *ui;QTcpSocket *m_socket;
};
#endif // WIDGET_H
#include "widget.h"
#include "ui_widget.h"#include <QHostAddress>Widget::Widget(QWidget *parent): QWidget(parent), ui(new Ui::Widget)
{ui->setupUi(this);ui->lineEdit_address->setText("192.168.2.24");ui->lineEdit_connect->setText("8888");//创建Socket对象,连接服务器m_socket = new QTcpSocket(this);connect(ui->pushButton_connect, &QPushButton::clicked, this, [=](){m_socket->connectToHost(QHostAddress(ui->lineEdit_address->text()), ui->lineEdit_connect->text().toInt());ui->pushButton_connect->setDisabled(true);ui->pushButton_close->setEnabled(true);});//断开连接connect(ui->pushButton_close, &QPushButton::clicked, this, [=](){m_socket->close();ui->pushButton_connect->setEnabled(true);ui->pushButton_close->setDisabled(true);});//数据交互connect(m_socket, &QTcpSocket::connected, this, [=](){ui->textEdit_history->append("服务器连接成功!!!!");});connect(m_socket, &QTcpSocket::readyRead, this, [=](){ui->textEdit_history->append("服务器说: " + m_socket->readAll());});connect(m_socket, &QTcpSocket::disconnected, this, [=](){ui->textEdit_history->append("服务器断开连接!!!!");});connect(ui->pushButton_send, &QPushButton::clicked, this, [=](){m_socket->write(ui->textEdit_send->toPlainText().toUtf8());ui->textEdit_history->append("客户端说: " + ui->textEdit_send->toPlainText().toUtf8());});
}Widget::~Widget()
{delete ui;
}

2.2.3 细节讲解

没啥可讲的,QT都封装好了,连接好就能直接用,比串口的请求响应简单方便多了。

2.2.4 演示

注意,先开启服务器,然后才能使用,局域网可以内部使用,外部使用需要申请IP。

2.3 线程中的使用

在实际项目中,数据的部分大多是写进线程的,关于线程的了解在前文中有讲述,需要的朋友可以自行查阅。

下面以文件从客户端传到服务器为例:

2.3.1 代码示例

2.3.1.1 Sever
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>
#include <QTcpServer>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();private slots:void on_pushButton_listen_clicked();private:Ui::MainWindow *ui;QTcpServer* m_server;};
#endif // MAINWINDOW_H
#ifndef ACCEPTFILE_H
#define ACCEPTFILE_H#include <QObject>
#include <QThread>
#include <QTcpSocket>class acceptfile : public QThread
{Q_OBJECT
public:explicit acceptfile(QTcpSocket* tcp, QThread *parent = nullptr);signals:void over();protected:void run() override;private:QTcpSocket* m_tcp;};#endif // ACCEPTFILE_H
#include "mainwindow.h"
#include "ui_mainwindow.h"#include "acceptfile.h"#include <QMessageBox>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);//创建服务器对象m_server = new QTcpServer(this);//创建套接字connect(m_server, &QTcpServer::newConnection, this, [=](){QTcpSocket* tcp = m_server->nextPendingConnection();//创建子线程acceptfile* subthread = new acceptfile(tcp);subthread->start();//释放资源connect(subthread, &acceptfile::over, this, [=](){subthread->quit();subthread->wait();subthread->deleteLater();QMessageBox::information(this, "文件接收", "文件接收完毕!!!!!!!");});});}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_pushButton_listen_clicked()
{m_server->listen(QHostAddress::Any, ui->lineEdit_port->text().toUShort());
}
#include "acceptfile.h"#include <QFile>acceptfile::acceptfile(QTcpSocket* tcp, QThread *parent) : QThread(parent)
{m_tcp = tcp;
}void acceptfile::run()
{//创建文件对象,保存客户端发送过来的文件内容QFile* file = new QFile("C:/Users/EDY/Desktop/QTtest/recv.txt");file->open(QFile::WriteOnly);//读取套接字socket的内容connect(m_tcp, &QTcpSocket::readyRead, this, [=](){static int total = 0;static int count = 0;if(count == 0){m_tcp->read((char*)&total, 4);}//读出剩余数据QByteArray all = m_tcp->readAll();count += all.size();file->write(all);//判断是否接收完毕if(total == count){m_tcp->close();m_tcp->deleteLater();file->close();file->deleteLater();emit over();}});//进入事件循环exec();
}
2.3.1.2 Client
#ifndef MAINWINDOW_H
#define MAINWINDOW_H#include <QMainWindow>#include <QThread>QT_BEGIN_NAMESPACE
namespace Ui { class MainWindow; }
QT_END_NAMESPACEclass MainWindow : public QMainWindow
{Q_OBJECTpublic:MainWindow(QWidget *parent = nullptr);~MainWindow();signals:void startconnect(unsigned short, QString);void sendFile(QString path);private slots:void on_connectserver_btn_clicked();void on_file_btn_clicked();void on_send_btn_clicked();private:Ui::MainWindow *ui;};
#endif // MAINWINDOW_H
#ifndef SENDFILE_H
#define SENDFILE_H#include <QObject>
#include <QTcpSocket>class sendfile : public QObject
{Q_OBJECT
public:explicit sendfile(QObject *parent = nullptr);//连接服务器void connectServer(unsigned short address, QString ip);//发送文件void sendFile(QString path);signals:void connectOK();void gameover();void curpercent(int);private:QTcpSocket* m_tcp;};#endif // SENDFILE_H
#include "mainwindow.h"
#include "ui_mainwindow.h"
#include "sendfile.h"#include <QFileDialog>
#include <QMessageBox>MainWindow::MainWindow(QWidget *parent): QMainWindow(parent), ui(new Ui::MainWindow)
{ui->setupUi(this);ui->port->setText("8888");ui->IP->setText("192.168.2.24");ui->progressBar->setRange(0, 100);ui->progressBar->setValue(0);//创建线程对象QThread* thrd = new QThread;//创建任务sendfile* worker = new sendfile;//将work放入子线程worker->moveToThread(thrd);//连接服务器connect(this, &MainWindow::startconnect, worker, &sendfile::connectServer);//连接文件发送connect(this, &MainWindow::sendFile, worker, &sendfile::sendFile);//处理连接服务器的子线程数据connect(worker, &sendfile::connectOK, this, [=](){QMessageBox::information(this, "连接服务器",  "连接成功!!!!");});connect(worker, &sendfile::gameover, this, [=](){//资源释放thrd->quit();thrd->wait();worker->deleteLater();thrd->deleteLater();});//处理选择文件发送子线程数据connect(worker, &sendfile::curpercent, ui->progressBar, &QProgressBar::setValue);//线程开始thrd->start();
}MainWindow::~MainWindow()
{delete ui;
}void MainWindow::on_connectserver_btn_clicked()
{QString ip = ui->IP->text();unsigned short port = ui->port->text().toUShort();emit startconnect(port, ip);
}void MainWindow::on_file_btn_clicked()
{QString path = QFileDialog::getOpenFileName();if(path.isEmpty()){QMessageBox::warning(this, "打开文件", "选择的文件路径不能为空!!");return;}ui->file->setText(path);
}void MainWindow::on_send_btn_clicked()
{emit sendFile(ui->file->text());
}
#include "sendfile.h"#include <QFile>
#include <QFileInfo>sendfile::sendfile(QObject *parent) : QObject(parent)
{}void sendfile::connectServer(unsigned short address, QString ip)
{m_tcp = new QTcpSocket;m_tcp->connectToHost(ip, address);connect(m_tcp, &QTcpSocket::connected, this, &sendfile::connectOK);connect(m_tcp, &QTcpSocket::disconnected, this, [=](){m_tcp->close();m_tcp->deleteLater();emit gameover();});
}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_tcp->write((char*)&filesize, 4);}QByteArray line = file.readLine();num += line.size();int percent = (num * 100 / filesize);emit curpercent(percent);m_tcp->write(line);}
}

2.3.2 代码讲解

没啥好讲的,可以看看代码,写得很详细,文件传输部分跟普通数据也是一样的,区别就是需要用到文件的类QFile和QFileInfo,一个是文件对象,一个是文件信息对象。简单来说指文件是QFile,指文件的具体数据是QFileInfo。源码已上传

2.3.3 演示

QTcp服务器与客户端

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

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

相关文章

网络链路层之(2)PPP协议

网络链路层之(2)PPP协议 Author: Once Day Date: 2024年3月27日 一位热衷于Linux学习和开发的菜鸟&#xff0c;试图谱写一场冒险之旅&#xff0c;也许终点只是一场白日梦… 漫漫长路&#xff0c;有人对你微笑过嘛… 全系列文章可参考专栏: 通信网络技术_Once-Day的博客-CSDN…

STM32学习笔记(6_8)- TIM定时器的编码器接口代码

无人问津也好&#xff0c;技不如人也罢&#xff0c;都应静下心来&#xff0c;去做该做的事。 最近在学STM32&#xff0c;所以也开贴记录一下主要内容&#xff0c;省的过目即忘。视频教程为江科大&#xff08;改名江协科技&#xff09;&#xff0c;网站jiangxiekeji.com 现在开…

【搜索引擎2】实现API方式调用ElasticSearch8接口

1、理解ElasticSearch各名词含义 ElasticSearch对比Mysql Mysql数据库Elastic SearchDatabase7.X版本前有Type&#xff0c;对比数据库中的表&#xff0c;新版取消了TableIndexRowDocumentColumnmapping Elasticsearch是使用Java开发的&#xff0c;8.1版本的ES需要JDK17及以上…

【unity】解决unity编译器安装中文汉化包失败

如果有的同学中文包安装失败&#xff0c;我们找到相应的编译器版本&#xff0c;点击在资源管理器中显示按钮&#xff0c; 我们点击当前目录的上一级&#xff0c;进入编译器目录。 找到modules.json文件双击打开 我们找到简体中文&#xff0c;复制downloadUrl后面的值到浏览…

云电脑安全性怎么样?企业如何选择安全的云电脑

云电脑在保障企业数字资产安全方面&#xff0c;采取了一系列严谨而全面的措施。随着企业对于数字化转型的深入推进&#xff0c;数字资产的安全问题日益凸显&#xff0c;而云电脑作为一种新兴的办公模式&#xff0c;正是为解决这一问题而生。云电脑安全吗&#xff1f;可以放心使…

Java常见限流用法介绍和实现

目录 一、现象 ​编辑 二、工具 ​​​​​​1、AtomicInteger,AtomicLong 原子类操作 ​​​​​​2、RedisLua ​​​​​​3、Google Guava的RateLimiter 1&#xff09; 使用 2&#xff09; Demo 3&#xff09; 优化demo 4、阿里开源的Sentinel 三、算法 1、计数…

『Apisix进阶篇』动态负载均衡:APISIX的实战演练与策略应用

&#x1f680;『Apisix系列文章』探索新一代微服务体系下的API管理新范式与最佳实践 【点击此跳转】 &#x1f4e3;读完这篇文章里你能收获到 &#x1f3af; 掌握APISIX中多种负载均衡策略的原理及其适用场景。&#x1f4c8; 学习如何通过APISIX的Admin API和Dashboard进行负…

python-pytorch获取FashionMNIST实际图片标签数据集

在查看pytorch官方文档的时候&#xff0c;在这里链接中https://pytorch.org/tutorials/beginner/basics/data_tutorial.html的Creating a Custom Dataset for your files章节&#xff0c;有提到要自定义数据集&#xff0c;需要用到实际的图片和标签。 在网上找了半天没找到&a…

Ceph——部署

Ceph简介 Ceph是一款开源的 SDS 分布式存储&#xff0c;它具备极高的可用性、扩展性和易用性&#xff0c;可用于存 储海量数据 Ceph的存储节点可部署在通用服务器上&#xff0c;这些服务器的 CPU 可以是 x86 架构的&#xff0c;也可以 是 ARM 架构的。 Ceph 存储节点之间相互…

政安晨:【深度学习神经网络基础】(一)—— 逐本溯源

政安晨的个人主页&#xff1a;政安晨 欢迎 &#x1f44d;点赞✍评论⭐收藏 收录专栏: 政安晨的机器学习笔记 希望政安晨的博客能够对您有所裨益&#xff0c;如有不足之处&#xff0c;欢迎在评论区提出指正&#xff01; 与计算机一样的古老历史 神经网络的出现可追溯到20世纪40年…

ubuntu22.04系统安装Opencv4.8.0+Opencv-contrib4.8.0

一、安装下载所需工具 1.打开终端&#xff0c;输入以下命令来更新软件源&#xff1a; sudo apt-get update 2.安装wget&#xff1a; sudo apt-get install wget 3.下载opencv和opencv-contrib包&#xff1a; wget -O opencv-4.8.0.zip https://github.com/opencv/opencv/…

【漏洞复现】网络验证系统getInfo接口处存在SQL注入漏洞

免责声明&#xff1a;文章来源互联网收集整理&#xff0c;请勿利用文章内的相关技术从事非法测试&#xff0c;由于传播、利用此文所提供的信息或者工具而造成的任何直接或者间接的后果及损失&#xff0c;均由使用者本人负责&#xff0c;所产生的一切不良后果与文章作者无关。该…

Remote Desktop Manager for Mac:远程桌面管理软件

Remote Desktop Manager for Mac&#xff0c;是远程桌面管理的理想之选。它集成了多种远程连接技术&#xff0c;无论是SSH、RDP还是VNC&#xff0c;都能轻松应对&#xff0c;让您随时随地安全访问远程服务器和工作站。 软件下载&#xff1a;Remote Desktop Manager for Mac下载…

【性能优化】 【回溯】 【字符串】1307. 口算难题

作者推荐 视频算法专题 本文涉及知识点 数学 回溯 字符串 性能优化 LeetCode1307. 口算难题 给你一个方程&#xff0c;左边用 words 表示&#xff0c;右边用 result 表示。 你需要根据以下规则检查方程是否可解&#xff1a; 每个字符都会被解码成一位数字&#xff08;0 - …

云原生(六)、CICD - Jenkins快速入门

Jenkuns快速入门 一、CICD概述 CICD是持续集成&#xff08;Continuous Integration&#xff09;和持续部署&#xff08;Continuous Deployment&#xff09;的缩写。它是软件开发中的一种流程和方法论&#xff0c;旨在通过自动化的方式频繁地将代码集成到共享存储库中&#xf…

策略路由-IP-Link-路由协议简介

策略路由 策略路由和路由策略的不同 1.策略路由的操作对象是数据包&#xff0c;在路由表已经产生的情况下&#xff0c;不按照路由表进行转发&#xff0c;而是根据需要&#xff0c;依照某种策略改变数据包的转发路径 2.路由策略的操作对象是路由信息。路由策略的主要实现了路…

nginx代理服务后,有关文件的操作无法执行,nginx代理jupyter或为知笔记后无法创建文件及文件夹,无法操作文件

nginx配置 server {listen 18001; # 修改转发的接口listen [::]:18001; # 修改转发的接口server_name _;root /usr/share/nginx/html;location / {proxy_pass http://127.0.0.1:7777; # 指定自己服务地址proxy_set_header Host $host;}# Load configurat…

服务器监控软件夜莺采集监控(三)

文章目录 一、采集器插件1. exec插件2. rabbitmq插件3. elasticsearch插件 二、监控仪表盘1. 系统信息2. 数据服务3. NginxMQ4. Docker5. 业务日志 一、采集器插件 1. exec插件 input.exec/exec.toml [[instances]] commands ["/home/monitor/categraf/scripts/*.sh&q…

【深度学习】图片预处理,分辨出模糊图片

ref:https://pyimagesearch.com/2015/09/07/blur-detection-with-opencv/ 论文 ref:https://www.cse.cuhk.edu.hk/leojia/all_final_papers/blur_detect_cvpr08.pdf 遇到模糊的图片&#xff0c;还要处理一下&#xff0c;把它挑出来&#xff0c;要么修复&#xff0c;要么弃用。否…

信号处理--情绪分类数据集DEAP预处理(python版)

关于 DEAP数据集是一个常用的情绪分类公共数据&#xff0c;在日常研究中经常被使用到。如何合理地预处理DEAP数据集&#xff0c;对于后端任务的成功与否&#xff0c;非常重要。本文主要介绍DEAP数据集的预处理流程。 工具 图片来源&#xff1a;DEAP: A Dataset for Emotion A…