qt udp tcp代替RPC

Posted qianbo_insist

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了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 的方式来做。这个等到下一次来讲了。

以上是关于qt udp tcp代替RPC的主要内容,如果未能解决你的问题,请参考以下文章

qt udp tcp代替RPC 图片AI服务器

qt udp tcp代替RPC 图片AI服务器

TCP/IP——何时用UDP代替TCP

Qt TCP/UDP 网络协议入门实操TCP通讯

Qt TCP/UDP 网络协议入门实操TCP通讯

Qt TCP/UDP 网络协议入门实操TCP通讯