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++形参与实参的区别实例解析

    C++形参与实参的区别实例解析

    这篇文章主要介绍了C++形参与实参的区别实例解析,需要的朋友可以参考下
    2014-07-07
  • C语言使用单链表实现学生信息管理系统

    C语言使用单链表实现学生信息管理系统

    这篇文章主要为大家详细介绍了C语言使用单链表实现学生信息管理系统,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下
    2021-11-11
  • C++使用函数的一些高级操作指南

    C++使用函数的一些高级操作指南

    C++中函数调用的方法与C语言并无区别,依旧是在调用方函数中执行函数调用语句来实现函数调用,下面这篇文章主要给大家介绍了关于C++使用函数的一些高级操作,文中通过图文介绍的非常详细,需要的朋友可以参考下
    2022-12-12
  • C语言中fchdir()函数和rewinddir()函数的使用详解

    C语言中fchdir()函数和rewinddir()函数的使用详解

    这篇文章主要介绍了C语言中fchdir()函数和rewinddir()函数的使用详解,是C语言入门学习中的基础知识,需要的朋友可以参考下
    2015-09-09
  • C++中箭头运算符的含义与用法讲解

    C++中箭头运算符的含义与用法讲解

    今天小编就为大家分享一篇关于C++中箭头运算符的含义与用法讲解,小编觉得内容挺不错的,现在分享给大家,具有很好的参考价值,需要的朋友一起跟随小编来看看吧
    2019-04-04
  • Objective-C中常用的结构体NSRange,NSPoint,NSSize(CGSize),NSRect实例分析

    Objective-C中常用的结构体NSRange,NSPoint,NSSize(CGSize),NSRect实例分析

    这篇文章主要介绍了Objective-C中常用的结构体NSRange,NSPoint,NSSize(CGSize),NSRect实例分析,有助于更加直观的理解Object-C常用的结构体,需要的朋友可以参考下
    2014-07-07
  • 详解C语言的mem系列函数

    详解C语言的mem系列函数

    这篇文章主要为大家详细介绍了C语言的mem系列函数,文中示例代码介绍的非常详细,具有一定的参考价值,感兴趣的小伙伴们可以参考一下,希望能够给你带来帮助
    2022-02-02
  • C++表达式new与delete知识详解

    C++表达式new与delete知识详解

    这篇文章主要为大家详细介绍了C++表达式new与delete知识点,学习如何动态创建对象,动态创建的对象与一般对象的区别,动态创建的对象的初始化以及释放动态分配的内存等知识点,感兴趣的朋友可以参考一下
    2016-05-05
  • C++11 模板参数的“右值引用”是转发引用吗

    C++11 模板参数的“右值引用”是转发引用吗

    这篇文章主要介绍了C++11 模板参数的“右值引用”是转发引用吗,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧
    2020-05-05
  • C++中const与#define的利弊分析

    C++中const与#define的利弊分析

    C++中不但可以用define定义常量还可以用const定义常量,下面这篇文章主要给大家分析介绍了关于C++中const与#define的利弊,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友可以参考下
    2018-05-05

最新评论