网站首页 > 教程文章 正文
Qt之使用socket实现远程控制
在前面的文章中介绍过Qt心跳包的实现方法,本篇文章将会介绍下位机通过心跳包和上位机之间进行数据交互和远程功能控制的实现方法。
首先介绍环境,下位机使用Qt作为主程序,上下位机使用TCP socket进行网络通信,上位机实现方式任意。下位机心跳包线程在进程一开始就启动,一直到进程结束才停止。
心跳包是一个始终独立的线程,首先要搭建框架:
main.cpp
#include <heartbeatthread.h>
//心跳包线程
heartbeatThread *ht = nullptr;
ht = new heartbeatThread;
ht -> start();
.h文件
【领QT开发教程学习资料,点击下方链接免费领取↓↓,先码住不迷路~】
点击→领取「链接」
#ifndef HEARTBEATTHREAD_H
#define HEARTBEATTHREAD_H
#include <QThread>
#include <QCoreApplication>
#include <QTimer>
#include <QTcpSocket>
#include <QHostAddress>
#include <QtConcurrent/QtConcurrent>
using namespace std;
class heartbeatThread : public QThread
{
Q_OBJECT
public:
explicit heartbeatThread(QObject *parent = nullptr);
void run(); //任务处理线程
~heartbeatThread(){
}
public slots:
private:
QTcpSocket *tcpSocket = nullptr;
protected:
};
#endif // HEARTBEATTHREAD_H
.cpp文件
#include "heartbeatthread.h"
heartbeatThread::heartbeatThread(QObject *parent)
{
}
void heartbeatThread::run()
{
tcpSocket = new QTcpSocket();
tcpSocket->connectToHost(QHostAddress("127.0.0.1"), 5000);
QtConcurrent::run([=]()
{
while(true)
{
try{ //收包
//将接收内容存储到字符串中
char recvMsg[1024] = {'\0'};
int recvRe = tcpSocket->read(recvMsg, 1024);
if(recvRe != 0 && recvRe != -1) //0:连接未发信息;-1:未连接
{
}
} catch(...){}
QEventLoop eventloop;
QTimer::singleShot(1, &eventloop, SLOT(quit()));
eventloop.exec();
}
});
while(true){
try{ //发包
//等待连接成功
if(!tcpSocket->waitForConnected(30000))
{
tcpSocket->connectToHost(QHostAddress("127.0.0.1"), 5000);
}
else
{
QByteArray block = "block";
tcpSocket->write(block);
tcpSocket->flush();
}
} catch(...){}
QEventLoop eventloop;
QTimer::singleShot(1000, &eventloop, SLOT(quit()));
eventloop.exec();
}
}
这样收发就写好了。
先说发包,这里是和上位机建立了长连接,我只需要知道上位机的IP和端口号即可建立连接,上位机不需要知道我的IP信息。如果上位机需要知道我的相关信息,可以在包中写入,并根据实际需要调整发送频率。这里有重连机制,上位机在一段时间没有收到我发送的信息后,可以认定我已经离线。
再说收包,其实就是不断地读入缓冲区的内容,缓冲区的大小和解析方式需要和上位机协调,尽量在包过大时进行拆包发送,下位机再根据解包信息判断是否需要接包,以及信息是否齐全、有没有丢包等。
收发框架搭好以后,就可以建立一定的收发规范进行远程控制了,发包比较灵活,这里只说收包。
比如设定这样的规则:上位机发送的所有的报文都有一段报文头,记录报文的总长度。报文头部后面接一段自定义的操作类型,用来进行指令分类。操作类型后接实际的操作指令。
代码如下。
try{ //收包
//将接收内容存储到字符串中
char recvMsg[1024] = {'\0'};
int recvRe = tcpSocket->read(recvMsg, 1024);
if(recvRe != 0 && recvRe != -1) //0:连接未发信息;-1:未连接
{
QString recvMessage = recvMsg;
//字符串解析
head = recvMessage.mid(0, HEAD_LENGTH).simplified(); //网络头,报文总长度
type = recvMessage.mid(HEAD_LENGTH, TYPE_LENGTH).simplified(); //请求类型
message = recvMessage.mid(HEAD_LENGTH + TYPE_LENGTH, recvMessage.length()).simplified(); //实际请求内容
//按照字符串要求分类处理
handle(type, message);
}
} catch(...){}
预先定好报文头部和指令类型的长度,就可以在收到包后按照位置对字符串进行解析。分离出请求类型和请求内容后,对指令进行处理即可。同时也需要定义一定的上位机指令发送规范。
【领QT开发教程学习资料,点击下方链接免费领取↓↓,先码住不迷路~】
点击→领取「链接」
处理示例:
void handle(QString type, QString message)
{
QStringList handleOptions;
handleOptions << "aaaa" << "bbbb" << "cccc" ;
/*
aaaa = 0
bbbb = 1
cccc = 2
*/
switch (handleOptions.indexOf(type)) {
case 0:
break;
case 1:
break;
case 2:
break;
default:
qDebug() << "do not understand!";
break;
}
}
这样,单台下位机的远程控制就完成了,多台机器的远程控制方法将在以后介绍。
猜你喜欢
- 2024-12-17 Qt使用教程:创建Qt Quick UI表单(三)
- 2024-12-17 一小例子,了解 TCP 通讯流程 | Qt 示例
- 2024-12-17 如何使用QT编写自己的串口调试助手软件
- 2024-12-17 Qt pro文件中的常用宏说明 qt pro宏定义
- 2024-12-17 Qt Creator 源码学习笔记01,初识QTC
- 2024-12-17 QT学习:statusBar的使用,创建控件添加到statusBar上面
- 2024-12-17 一口气,了解 Qt 的所有 IPC 方式 | Qt 速学
- 2024-12-17 Qt线程QThread开启和安全退出 qt线程怎么安全关闭
- 2024-12-17 C/C++编程笔记:编写完成了一个C/C++程序,如何做一个界面出来?
- 2024-12-17 Qt实现炫酷启动图-动态进度条 qt静态编译独立可执行文件
- 最近发表
- 标签列表
-
- location.href (44)
- document.ready (36)
- git checkout -b (34)
- 跃点数 (35)
- 阿里云镜像地址 (33)
- qt qmessagebox (36)
- md5 sha1 (32)
- mybatis plus page (35)
- semaphore 使用详解 (32)
- update from 语句 (32)
- vue @scroll (38)
- 堆栈区别 (33)
- 在线子域名爆破 (32)
- 什么是容器 (33)
- sha1 md5 (33)
- navicat导出数据 (34)
- 阿里云acp考试 (33)
- 阿里云 nacos (34)
- redhat官网下载镜像 (36)
- srs服务器 (33)
- pico开发者 (33)
- https的端口号 (34)
- vscode更改主题 (35)
- 阿里云资源池 (34)
- os.path.join (33)