Qt网络通信

1. UDP通信

1.1 udp通信的基本流程

创建套接字

绑定套接字

进行通信

关闭套接字

涉及到的类和信号

QUdpSocket:Udp套接字类,类对象就是一个udp套接字对象
QHostAddress:ip地址类
void readyRead():信号,当有数据到达可读,就会产生这个信号

1.2 举例

通信端1

udp1

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QUdpSocket>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private slots:
    void on_pushButton_clicked();

    //当有数据到达时的槽
    void readdate();
private:
    Ui::Widget *ui;

    //创建udp对象
    QUdpSocket* socket;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"

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

    //1. 创建udp套接字
    socket = new QUdpSocket;

    //2. 绑定
    //ip地址类,直接构造设置ip地址
    QHostAddress addr("192.168.124.33");
    //addr.setAddress();//函数设置ip地址
    socket->bind(addr,10000);


    //绑定readyRead信号,当有数据到达时,就会触发信号,去接收数据
    connect(socket,SIGNAL(readyRead()),this,SLOT(readdate()));

}

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

//发送数据
void Widget::on_pushButton_clicked()
{
    //发送数据
    //定义缓冲区
    QByteArray data = ui->textEdit_2->toPlainText().toLocal8Bit();//toLocal8Bit()将数据转换为QByteArray类型
    socket->writeDatagram(data,QHostAddress("192.168.124.33"),10001);
}

//接收数据
void Widget::readdate(){

    //定义缓冲区
    QByteArray data;
    data.resize(1024);

    //读发来的数据存,储到data中
    QHostAddress addr;
    quint16 port;
    //size是收到的数据大小
    int size = socket->readDatagram(data.data(),data.size(),&addr,&port);//参数addrr,port是发送方的ip和端口

    data.resize(size);

    //展示数据
    ui->textEdit->append("发送端的ip:"+addr.toString()+"  port:"+QString::number(port));
    ui->textEdit->append(data);
}


通信端2

udp2

widget.h

widget.cpp

运行

2. TCP通信

2.1 客户端通信流程 QTcpSocket

1. 创建套接字

2. 绑定套接字

3. 连接服务器

4. 进行通信

5. 关闭套接字

2.1.1 涉及的信号 

connected():信号,当连接服务器且连接成功

readyRead():信号,当发送给数据到套接字,套接字可读

disconnected():信号,只要套接字断开连接,就会产生

2.2 服务端通信流程 QTcpServer

1. 创建套接字

2绑定套接字

3监听套接字---套接字类型改变改为监听套接字

4连接客户端---得到与客户端进行通信的套接字

5进行通信

6关闭套接字

相关函数

nextPendingConnection():服务器建立与客户端连接,返回值 QTcpScket 类对象:通信套接字对象

2.2.1 涉及的信号

newConnection():信号,当有新的客户端连接时,会产生这个信号

readyRead():信号,当发送给数据到套接字,套接字可读

disconnected():信号,只要套接字断开连接,就会产生

2.2 举例:模拟客户端和服务端通信

2.2.1 客户端

tcp_client

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpSocket>
#include <QHostAddress>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private slots:
    void on_pushButton_connect_clicked();

    //当连接服务器,且连接成功的槽
    void socket_conn();

    void on_pushButton_send_clicked();

    //当有数据发来时,触发该信号
    void readdata();

    void on_pushButton_duankai_clicked();

    //当连接断开,触发该信号
    void socket_disconn();

private:
    Ui::Widget *ui;

    //创建tcp对象
    QTcpSocket* socket;
};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"


//tcp通信客户端
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //1.创建套接字对象
    socket = new QTcpSocket;

    //2.绑定,这里其实可以不用绑定,系统会自动给你分配
    socket->bind(QHostAddress("192.168.124.33"),9999);

    //设置连接按钮可点击,发送和点击不可点
    ui->pushButton_connect->setEnabled(true);
    ui->pushButton_send->setEnabled(false);
    ui->pushButton_duankai->setEnabled(false);

}

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


//连接服务器
void Widget::on_pushButton_connect_clicked()
{
    //3. 连接服务器,参数1服务端ip,参数2服务端端口
    socket->connectToHost(ui->lineEdit_ip->text(),ui->lineEdit_port->text().toUShort());//toUShort() 字符串转为数字


    //提示,注意这里的信号和槽的绑定写在连接按钮里,后面会有个问题,就是每连接一次信号和槽都会再绑定一次,造成多次重复绑定
    //要解决问题,就需要在断开连接哪里把绑定的信号和槽断开
    //如果把信号和槽的绑定写在上面的构造里就不会有这个问题了
    
    //当连接服务器,且连接成功,就会触发该信号
    connect(socket,SIGNAL(connected()),this,SLOT(socket_conn()));

    //当有数据发来时,触发该信号
    connect(socket,SIGNAL(readyRead()),this,SLOT(readdata()));

    //当连接断开,触发该信号
    connect(socket,SIGNAL(disconnected()),this,SLOT(socket_disconn()));
}

//当连接服务器,且连接成功,触发的信号对应的槽
void Widget::socket_conn(){
    //接收框里提示连接成功
    ui->textEdit_receice->append(ui->lineEdit_ip->text()+":"+ui->lineEdit_port->text()+"  connect ok");

    //设置连接按钮不可点击,断开和发送可点击
    ui->pushButton_connect->setEnabled(false);
    ui->pushButton_send->setEnabled(true);
    ui->pushButton_duankai->setEnabled(true);
}


//点击发送数据给服务器
void Widget::on_pushButton_send_clicked()
{
    //4.将数据发送给服务器
    //toStdString().c_str()先转为c++标准字符串,再转为c字符串
    socket->write(ui->textEdit_write->toPlainText().toStdString().c_str());

}

//当有数据发来时,接收数据
void Widget::readdata(){
    //5.读取数据
    QByteArray data =  socket->readAll();
    ui->textEdit_receice->append(data);
}


//客户端断开与服务器的连接
void Widget::on_pushButton_duankai_clicked()
{
    //6.断开与服务端的连接
    socket->disconnectFromHost();

}

//连接断开后要做到处理  对应的槽(只要连接断开就会进入这个槽函数)
void Widget::socket_disconn(){
    //接收框里提示连接断开
    ui->textEdit_receice->append(ui->lineEdit_ip->text()+":"+ui->lineEdit_port->text()+"  disconnect");

    //把绑定的信号和槽断开
    disconnect(socket,SIGNAL(connected()),this,SLOT(socket_conn()));
    disconnect(socket,SIGNAL(readyRead()),this,SLOT(readdata()));
    disconnect(socket,SIGNAL(disconnected()),this,SLOT(socket_disconn()));

    //设置连接按钮可点击,发送和点击不可点
    ui->pushButton_connect->setEnabled(true);
    ui->pushButton_send->setEnabled(false);
    ui->pushButton_duankai->setEnabled(false);
}

测试使用网络调试助手E:\peixunqianrushi_ziliao\网络调试助手

连接

发送数据

点击断开连接

2.2.2 服务端

服务器设置为多线程---并发服务器,每个客户端在线程中进行操作

tcp_server

widget.h

#ifndef WIDGET_H
#define WIDGET_H

#include <QWidget>
#include <QTcpServer>
#include <QTcpSocket>
#include <thread_tcp.h>

QT_BEGIN_NAMESPACE
namespace Ui { class Widget; }
QT_END_NAMESPACE

class Widget : public QWidget
{
    Q_OBJECT

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

private slots:
    void on_pushButton_start_clicked();

    //当有新的客户端连接时的槽
    void new_conn_arrive();

    void on_pushButton_end_clicked();

private:
    Ui::Widget *ui;

    //实例化tcp对象
    QTcpServer* server;

    //存储的socket就是与客户端的通信套接字
    QTcpSocket* socket1;

    //存储所有的通信套接字
    QList<QTcpSocket*> list;

};
#endif // WIDGET_H

widget.cpp

#include "widget.h"
#include "ui_widget.h"


//tcp通信服务端
Widget::Widget(QWidget *parent)
    : QWidget(parent)
    , ui(new Ui::Widget)
{
    ui->setupUi(this);

    //1.创建tcp服务端套接字
    server = new QTcpServer;

    //2.绑定,这里提示,在qt中绑定和监听写在一起了,都在listen函数中

    //当有新的客户端连接时,就会触发该信号
    connect(server,SIGNAL(newConnection()),this,SLOT(new_conn_arrive()));

}

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


//启动服务器
void Widget::on_pushButton_start_clicked()
{
    //3.监听,这里提示,在qt中绑定和监听写在一起了
    server->listen(QHostAddress("192.168.124.33"),8888);
    ui->textEdit->append("服务器启动成功~~~");

}


//当有新的客户端连接请求时,触发该信号对应的槽函数
//建立连接
void Widget::new_conn_arrive(){

    //4.服务器建立与客户端的连接
    //现在的socket1就是与客户端的通信套接字
    socket1 = server->nextPendingConnection();
    //提示客户端连接成功
    socket1->write("connect success~~~~~~~");
    //将通信套接字添加进链表
    list.append(socket1);


    //从这里使用线程
    //把与客户端通信的套接字,放入线程中,使用线程来操作套接字与客户端通信
    //创建线程,有一个客户端就创建一个线程
    thread_tcp* tcp = new thread_tcp;
    //把通信套接字给线程
    tcp->socket = socket1;

    //当客户端发来消息,就会触发 在线程中的 写的槽函数,去读取客户端消息
    connect(tcp->socket,SIGNAL(readyRead()),tcp,SLOT(readdata()));

    //客户端断开连接,触发信号调用 线程中的槽,使线程关闭
    connect(tcp->socket,SIGNAL(disconnected()),tcp,SLOT(dis_conn()));


    //启动线程
    tcp->start();

}


//关闭服务器
void Widget::on_pushButton_end_clicked()
{
    for(int i=0;i<list.size();i++){
        //服务端关闭通信套接字的连接
        list.at(i)->disconnectFromHost();
    }

    list.clear();

    //关闭监听
    server->close();

    ui->textEdit->append("服务端已经关闭连接~~~~~~~");
}


thread_tcp.h

#ifndef THREAD_TCP_H
#define THREAD_TCP_H

#include <QThread>
#include <QTcpSocket>
#include <QDebug>

class thread_tcp : public QThread
{
    Q_OBJECT
public:
    thread_tcp();

    //socket就是与客户端的通信套接字
    QTcpSocket* socket;

    //执行线程的run
    void run();


public slots:
    //当客户端发来消息的槽
    void readdata();

    //只要客户端断开,就关闭线程
    void dis_conn();

};

#endif // THREAD_TCP_H

thread_tcp.cpp

#include "thread_tcp.h"

thread_tcp::thread_tcp()
{

}

//当客户端发来消息,读数据
void thread_tcp::readdata(){

    //读出数据
    QByteArray data = socket->readAll();

    //给客户端返回数据
    socket->write(data);

}

//一直执行线程
void thread_tcp::run(){
    qDebug()<<"线程执行";
    //阻塞执行
    exec();
}

//客户端断开连接时,关闭线程
void thread_tcp::dis_conn(){
    qDebug()<<"线程关闭";
    exit(0);
}

测试

运行服务端

启动客户端和网络调试助手,分别充当两个客户

分别连接,成功

发送数据,成功

分别断开连接,成功

再次分别连接,测试服务端关闭功能

关闭成功

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

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

相关文章

曲线生成 | 图解三次样条曲线生成原理(附ROS C++/Python/Matlab仿真)

目录 0 专栏介绍1 什么是样条&#xff1f;2 三次样条曲线原理2.1 曲线插值2.2 边界条件2.3 系数反解 3 算法仿真3.1 ROS C仿真3.2 Python仿真3.3 Matlab仿真 0 专栏介绍 &#x1f525;附C/Python/Matlab全套代码&#x1f525;课程设计、毕业设计、创新竞赛必备&#xff01;详细…

vue3-图片懒加载指令实现

图片懒加载&#xff1a;有些网站页面比较长&#xff0c;用户不一定访问到页面靠下面的图片&#xff0c;这类图片通过懒加载优化手段可以做到只有进入视口区域才发送图片请求 指令用法 //在图片img身上绑定指令&#xff0c;该图片只有正式进入到视口区域时才会发送图片网络请求…

腾讯云tsf平台-部署微服务项目

腾讯云tsf平台-部署微服务项目 一、腾讯云tsf平台简介二、部署准备0&#xff08;数据库、中间件等部署&#xff09;三、部署准备1&#xff08;创建集群和命名空间&#xff09;1、准备部署资源--集群2、使用容器部署微服务步骤 1&#xff1a;创建容器集群步骤 2&#xff1a;创建…

Linux服务部署,遇到的各种问题之一(测试篇)

最近服务器需要搬迁&#xff0c;所有的服务都需要迁移&#xff0c;从初始化数据盘&#xff0c;到服务部署的各种细节&#xff0c;下面我们一一来说 初始化数据盘就不用说了&#xff0c;大概率&#xff0c;作为测试接触不到。 今天来说是ubuntu显示的中文文件乱码问题如何解决…

Spring 事务原理一

从本篇博客开始&#xff0c;我们将梳理Spring事务相关的知识点。在开始前&#xff0c;想先给自己定一个目标&#xff1a;通过此次梳理要完全理解事务的基本概念及Spring实现事务的基本原理。为实现这个目标我想按以下几个步骤进行&#xff1a; 讲解事务中的一些基本概念使用Sp…

NTFS 磁盘管理器---NTFS Disk by Omi NTFS中文

NTFS Disk by Omi NTFS是一款专为Mac用户设计的NTFS磁盘管理工具。它可以帮助用户方便地访问和管理NTFS格式的硬盘、U盘、移动硬盘以及其他存储设备&#xff0c;并提供高效稳定的NTFS卷管理功能。该软件具有简单的用户界面&#xff0c;使用户能够快速访问和管理NTFS磁盘上的文件…

1.2 数据模型

数据模型是对现实世界数据特征的抽象&#xff0c;是现实世界的模拟 数据模型是用来描述数据、组织数据和对数据进行操作的 数据模型应满足三方面要求&#xff1a; 1 能比较真实地模拟现实世界 2 容易为人所理解 3 便于在计算机上实现 数据模型…

python算法与数据结构(搜索算法和拓扑排序算法)---深度优先搜索

课程目标 了解树/图的深度遍历&#xff0c;宽度遍历基本原理&#xff1b;会使用python语言编写深度遍历&#xff0c;广度遍历代码&#xff1b;掌握拓扑排序算法 搜索算法的意义和作用 搜索引擎 提到搜索两个子&#xff0c;大家都应该会想到搜索引擎&#xff0c;搜索引擎的基…

决策树的分类

概念 决策树是一种树形结构 树中每个内部节点表示一个特征上的判断&#xff0c;每个分支代表一个判断结果的输出&#xff0c;每个叶子节点代表一种分类结果 决策树的建立过程 1.特征选择&#xff1a;选取有较强分类能力的特征。 2.决策树生成&#xff1a;根据选择的特征生…

C#实现基于Word保护性模板文件的修改

目录 制作一个保护性模板文件 给文件设置保护密码 设计模板内容 限制编辑 进一步的需求 范例运行环境 Office DCOM 配置 设计实现 进一步修改模板文件 设置和取消保护 遍历WORD内容控件 总结 制作一个保护性模板文件 在类似一些OA的自动化处理或审批类系统里&a…

Python文件操作和异常处理:高效处理数据的利器

文章目录 一、引言1.1 文件操作和异常处理对于编程的重要性1.2 Python作为实现文件操作和异常处理的强大工具 二、为什么学习文件操作和异常处理2.1 处理各种文件格式&#xff1a;从文本到图像到音频等2.2 确保代码的鲁棒性&#xff1a;有效处理异常情况 三、文件读取和写入3.1…

如何让亚马逊,速卖通,美客多店铺排名和流量稳定爬升

一、关键词优化 关键词是亚马逊店铺排名的关键。通过合理的关键词优化&#xff0c;可以提高店铺的曝光率。卖家需要研究消费者的搜索习惯和行为&#xff0c;了解他们使用哪些关键词进行搜索&#xff0c;然后将这些关键词用于商品描述、标题和元数据中。此外&#xff0c;还可以…

GEE:最小距离分类器(minimumDistance)分类教程(样本制作、特征添加、训练、精度、最优参数、统计面积)

作者:CSDN @ _养乐多_ 本文将介绍在Google Earth Engine (GEE)平台上进行最小距离分类(minimumDistance)的方法和代码,其中包括制作样本点教程(本地、在线和本地在线混合制作样本点,合并样本点等),加入特征变量(各种指数、纹理特征、时间序列特征、物候特征等),运行…

PCIe-6328 八口USB3.0图像采集卡:专为工业自动化和机器视觉设计

PCIe-6328一块8口USB 3.0主控卡&#xff0c;专为工业自动化和机器视觉相关应用设计。USB 3.0或称作高速USB&#xff0c;是一项新兴总线技术&#xff0c;10倍于USB2.0的传输速度&#xff0c;尤其适用于高速数据存储和图 像设备。 绝大多数现有USB 3.0卡兼用多个接口于一个USB 3…

中仕教育:国考调剂和补录的区别是什么?

国考笔试成绩和进面名单公布之后&#xff0c;考生们就需要关注调剂和补录了&#xff0c;针对二者之间的区别很多考生不太了解&#xff0c;本文为大家解答一下关于国考调剂和补录的区别。 1.补录 补录是在公式环节之后进行的&#xff0c;主要原因是经过面试、体检和考察&#…

喝酒高境界:微醺和断片之间找到平衡

云仓酒庄的品牌雷盛红酒LEESON分享喝酒追求放松&#xff0c;喝的刚刚好就是微醺状态&#xff0c;喝大了就会断片。所以有人说&#xff0c;喝酒最高的境界是在微醺与断片之间找到一种平衡。 微醺是指稍有酒意但完全清醒且没有任何不良反应&#xff0c;可以散步走回家&#xff0c…

5118会员优惠码,拿走不谢,2024年最新的优惠码

5118大数据平台会员优惠码【yhm666】&#xff0c;结算时勾选“使用优惠码”&#xff0c;然后在优惠码窗口中输入yhm666&#xff0c;然后点确定即可享受特价会员价格。阿腾云atengyun.com分享如下图&#xff1a; 5118会员优惠码【yhm666】 5118会员价格和使用优惠码之后的价格对…

ctfshow-反序列化(web267-web270)

目录 web267 web268 web269 web270 总结 web267 页面用的什么框架不知道 看源码看一下 框架就是一种软件工具&#xff0c;它提供了一些基础功能和规范&#xff0c;可以帮助开发者更快地构建应用程序。比如Yii框架和ThinkPHP框架就是两个流行的PHP框架&#xff0c;它们提供…

租赁一台同传设备,哪里比较专业呢

我们知道 &#xff0c;同声传译设备在会议、演讲或其他语言交流场合中发挥着至关重要的作用。它们能够实现不同语言之间的即时翻译&#xff0c;让与会者或听众更准确地理解会议或演讲的内容。对于跨国会议或活动&#xff0c;同声传译设备是确保语言沟通顺畅的必要工具。那么&am…

如何搭建MariaDB并实现无公网ip环境远程连接本地数据库

&#x1f308;个人主页: Aileen_0v0 &#x1f525;热门专栏: 华为鸿蒙系统学习|计算机网络|数据结构与算法 ​&#x1f4ab;个人格言:“没有罗马,那就自己创造罗马~” 文章目录 1. 配置MariaDB数据库1.1 安装MariaDB数据库1.2 测试局域网内远程连接 2. 内网穿透2.1 创建隧道映射…