当前位置: 首页 > news >正文

qt udp tcp代替RPC(一)

qt远程通信

qt和其他远程进程通信可以使用直接的tcp udp,也可以使用封装的RPC,比如thrift,buttonpc,不过这些东西在程序需要特别简单处理的时候就显得没有必要。我们可以使用简单的udp通信来代替RPC。我们要设计一种协议方式,避免udp通信过于脆弱。

qt udp 通信

看如下界面
在这里插入图片描述
我们启动一个sokit 来启动udp服务
在这里插入图片描述
输入信息,点击发送,server端就收到了信息

#include "mainwindow.h"
#include "ui_mainwindow.h"

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

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


void MainWindow::on_pushButton_clicked()
{
    QByteArray dataGram=ui->lineEdit->text().toUtf8();

    QHostAddress address(ui->lineEdit_2->text());
    v_sender->writeDatagram(dataGram.data(),
                               dataGram.size(),
                            address,
                               6666);

}

代码特别简单,不过udp有个特点,就是容易丢包,我们设计一种机制,来避免udp 太过脆弱。我们规定udp 必须收到包必须返回,并且把udp收发放到线程中。

上面发包,那么能否既能发包又能收包?是可以的,这个分为两种情况,一种是局域网,一种是在云端,作为云端服务端记住IP和端口,发送心跳,局域网里面没有问题,在云端不一定能维持链接,断开时可以重新启动udp,再发送心跳。

connect(v_sender, SIGNAL(readyRead()), this, SLOT(readPendingDatagrams()));
void MainWindow::readPendingDatagrams()
{
    while(v_sender->hasPendingDatagrams()){

        QHostAddress srcAddress;
        quint16 nSrcPort;
        QByteArray datagram;
        datagram.resize(v_sender->pendingDatagramSize());
        v_sender->readDatagram(datagram.data(), datagram.size(), &srcAddress, &nSrcPort);
        qDebug()<<datagram.toStdString().data();
    }
}
void MainWindow::closeEvent(QCloseEvent *event)
{
    Q_UNUSED(event)
    v_sender->abort();
    QEventLoop loop;
    QTimer::singleShot(1000, &loop, SLOT(quit()));
    loop.exec();
    this->close();
}

在这里插入图片描述
测试工具中sokit 中的当前链接选中,发送数据,
udp在这里插入图片描述
udp这里收到了数据打印。当然外网和云端方式不这时候最好使用还是tcp来做。

使用tcp

tcp 链接和udp链接类似,没有多大区别,不过,传输层tcp协议拥有传输控制方法,拥塞控制和丢包重传机制,udp是没有的,以下是简单的启动方法

socket = new QTcpSocket();
  
    //连接信号槽
 QObject::connect(socket, &QTcpSocket::readyRead, this, &MainWindow::socket_Read_Data);
 QObject::connect(socket, &QTcpSocket::disconnected, this, &MainWindow::socket_Disconnected);

使用tcp 可以使用上次文章中的movetoThread 方法,把tcp的行为操作放到一个线程中,也可以继承一个QThread, 覆盖run方法,由于异步执行,使用connect将server 的newConnection 直接写入lamba函数之中,然后在lamba线程中启动一个tcp链接线程,应对

#include "widget.h"
#include "ui_widget.h"
#include <QMessageBox>
void close()
{
            myqtread->quit();
            myqtread->wait();
            myqtread->deleteLater();
 } 
Widget::Widget(QWidget *parent) :
    QWidget(parent),
    ui(new Ui::Widget)
{
    ui->setupUi(this);
  
    // 设置端口号
    ui->port->setText("6666");
  
    this->tcp_server = new QTcpServer(this);
    // 检验是否接收客户端的连接
    connect(this->tcp_server, &QTcpServer::newConnection, this, [=]()
    {
        QTcpSocket * tcp = this->m_server->nextPendingConnection();
        MyQThread * myqtread = new MyQThread(tcp);
        myqtread->start();
        // 获取子线程中发来的客户端端口的消息
        connect(myqtread, &MyQThread::ClientDisconnect, this, [=]()
        {
            QMessageBox::warning(this, "警告", "客户端已断开连接...");
        });
        connect(myqtread, &MyQThread::OverRecveid, this, [=]()
        {
            QMessageBox::information(this, "提示", "已接收文客户端发来的数据");
            tcp->close();
            tcp->deleteLater();
           close();

        });
    });
}
  
Widget::~Widget()
{
    delete ui;
}
// 点击监听按钮 进行监听 按钮转到槽的方式
void Widget::on_listenBtn_clicked()
{
    //获取端口号
    unsigned short port = ui->port->text().toUShort();
    //利用this->m_s 调用listen 进行监听
    this->m_server->listen(QHostAddress::Any, port);
}

序列化等其他RPC工作

其他工作我们可以使用二进制来代替json方式的发送,不过自己解析需要花时间,确实没有RPC工具来得方便,不过很多工作,我们可以使用调用脚本 lua 的方式来做。这个等到下一次来讲了。

相关文章:

  • 刷题记录:牛客NC50965Largest Rectangle in a Histogram
  • 在线副业教程之 02 你学的越多,你赚的越多+你必须开始学习的5个最好的在线副业
  • VUE | key的内部原理、Vue监测数据的原理、Vue.set()和vm.$set()的使用
  • Centos/Docker 环境中文乱码如何解决
  • VS2019 Qt源码编译
  • Linux8-fork父子进程逻辑地址相同、进程的逻辑地址与物理地址、fork相关例题、僵死进程
  • java毕业设计普通中学体育卫生信息管理系统源码+lw文档+mybatis+系统+mysql数据库+调试
  • 基于C语言的查找算法汇编
  • 多网段多通道IP地址和通讯端口转换
  • 【PyQt】PyQt入门安装和Hello World
  • 怎样创建一个VUE项目(超简单)
  • C++【STL】【queue的使用和模拟实现】【priority_queue的使用和模拟实现】
  • SAP PI PO 接口常见问题处理:在监控器中找不到一个或多个 XI 消息的日志记录
  • L2TP客户端之Strongswan移植(三)
  • matplotlib入门之抛砖引玉
  • CoolViewPager:即刻刷新,自定义边缘效果颜色,双向自动循环,内置垂直切换效果,想要的都在这里...
  • css系列之关于字体的事
  • exif信息对照
  • Git初体验
  • SpingCloudBus整合RabbitMQ
  • vue-router的history模式发布配置
  • 阿里云购买磁盘后挂载
  • 分享自己折腾多时的一套 vue 组件 --we-vue
  • 前端工程化(Gulp、Webpack)-webpack
  • 数组大概知多少
  • 通过git安装npm私有模块
  • 阿里云重庆大学大数据训练营落地分享
  • #HarmonyOS:基础语法
  • $redis-setphp_redis Set命令,php操作Redis Set函数介绍
  • (10)工业界推荐系统-小红书推荐场景及内部实践【排序模型的特征】
  • (3)nginx 配置(nginx.conf)
  • (C语言)输入自定义个数的整数,打印出最大值和最小值
  • (Matalb时序预测)PSO-BP粒子群算法优化BP神经网络的多维时序回归预测
  • (二)pulsar安装在独立的docker中,python测试
  • (论文阅读笔记)Network planning with deep reinforcement learning
  • (一)插入排序
  • .NET HttpWebRequest、WebClient、HttpClient
  • .net 前台table如何加一列下拉框_如何用Word编辑参考文献
  • .NET6使用MiniExcel根据数据源横向导出头部标题及数据
  • .Net接口调试与案例
  • ;号自动换行
  • @ 代码随想录算法训练营第8周(C语言)|Day57(动态规划)
  • @reference注解_Dubbo配置参考手册之dubbo:reference
  • [Angular] 笔记 20:NgContent
  • [JavaEE] 线程与进程的区别详解
  • [Jquery] 实现鼠标移到某个对象,在旁边显示层。
  • [Latex] \bibitem{} | .bbl 格式参考文献转换与获得
  • [LeetCode][面试算法]逻辑闭环的二分查找代码思路
  • [LLM]大模型八股知识点(一)
  • [MySQL FAQ]系列 -- 账号密码包含反斜线时怎么办
  • [NISACTF 2022]join-us
  • [NOIP2003 普及组] 乒乓球(模拟)
  • [one_demo_6]逆置整数
  • [POJ - 2386]
  • [PyQt] Pycharm 配置 PyQt 开发环境