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的主要内容,如果未能解决你的问题,请参考以下文章