Qt开发之使用socket实现远程控制

 更新时间:2022年11月19日 09:52:37   作者:音视频开发老舅  
本篇文章将会介绍下位机通过心跳包和上位机之间进行数据交互和远程功能控制的实现方法。文中的示例代码讲解详细,感兴趣的可以了解一下

Qt之使用socket实现远程控制

在前面的文章中介绍过Qt心跳包的实现方法,本篇文章将会介绍下位机通过心跳包和上位机之间进行数据交互和远程功能控制的实现方法。

首先介绍环境,下位机使用Qt作为主程序,上下位机使用TCP socket进行网络通信,上位机实现方式任意。下位机心跳包线程在进程一开始就启动,一直到进程结束才停止。

心跳包是一个始终独立的线程,首先要搭建框架:

main.cpp

#include <heartbeatthread.h>
 
    //心跳包线程
    heartbeatThread *ht = nullptr;
    ht = new heartbeatThread;
    ht -> start();

.h文件

#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(...){}

预先定好报文头部和指令类型的长度,就可以在收到包后按照位置对字符串进行解析。分离出请求类型和请求内容后,对指令进行处理即可。同时也需要定义一定的上位机指令发送规范。

处理示例:

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;
    }
}
 

到此这篇关于Qt开发之使用socket实现远程控制的文章就介绍到这了,更多相关Qt socket远程控制内容请搜索脚本之家以前的文章或继续浏览下面的相关文章希望大家以后多多支持脚本之家!

相关文章

  • C++实现LeetCode(110.平衡二叉树)

    C++实现LeetCode(110.平衡二叉树)

    这篇文章主要介绍了C++实现LeetCode(110.平衡二叉树),本篇文章通过简要的案例,讲解了该项技术的了解与使用,以下就是详细内容,需要的朋友可以参考下
    2021-07-07
  • C语言使用realloc函数实现通讯录源码分析

    C语言使用realloc函数实现通讯录源码分析

    什么是动态通讯录,就是在静态的基础上改进了一下,不在使用数组,而是使用指针和动态内存开辟的函数,当空间不够的时候,便进行增容
    2023-02-02
  • C++实现乒乓球比分判定

    C++实现乒乓球比分判定

    这篇文章主要为大家详细介绍了C++实现乒乓球比分判定,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2020-05-05
  • C语言return知识点总结

    C语言return知识点总结

    在本篇文章里小编给大家整理的是关于C语言return知识点总结内容,需要的朋友们可以学习参考下。
    2020-02-02
  • C++ 线段树原理与实现示例详解

    C++ 线段树原理与实现示例详解

    这篇文章主要为大家介绍了C++ 线段树原理与实现示例详解,有需要的朋友可以借鉴参考下,希望能够有所帮助,祝大家多多进步,早日升职加薪
    2022-09-09
  • C++浅析序列数据封装与优化实现方法

    C++浅析序列数据封装与优化实现方法

    封装是面向对象编程中的把数据和操作数据的函数绑定在一起的一个概念,这样能避免受到外界的干扰和误用,从而确保了安全,数据封装是一种把数据和操作数据的函数捆绑在一起的机制,数据抽象是一种仅向用户暴露接口而把具体的实现细节隐藏起来的机制
    2022-12-12
  • Opencv Hough算法实现图片中直线检测

    Opencv Hough算法实现图片中直线检测

    这篇文章主要为大家详细介绍了Opencv Hough算法实现图片中直线检测,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2018-12-12
  • C++实现闹钟程序的方法

    C++实现闹钟程序的方法

    这篇文章主要介绍了C++实现闹钟程序的方法,比较实用的功能,需要的朋友可以参考下
    2014-08-08
  • C语言陷阱与缺陷之数组越界访问详解

    C语言陷阱与缺陷之数组越界访问详解

    这篇文章主要为大家详细介绍了C语言的数组越界访问,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • C++简明分析讲解布尔类型及引用

    C++简明分析讲解布尔类型及引用

    布尔型(Boolean),是一种类型变量类型,引用(reference)就是C++对C语言的重要扩充。引用就是某一变量(目标)的一个别名,对引用的操作与对变量直接操作完全一样
    2022-04-04

最新评论