您当前的位置: 首页 >  udp

暂无认证

  • 13浏览

    0关注

    93978博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

qt udp tcp代替RPC(一)

发布时间:2022-09-24 15:02:18 ,浏览量:13

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  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 的方式来做。这个等到下一次来讲了。

关注
打赏
1655516835
查看更多评论
立即登录/注册

微信扫码登录

0.0515s