libvncclient编写多线程qt的VNC客户端

发布于:2024-09-05 ⋅ 阅读:(13) ⋅ 点赞:(0)

概述

  • 使用qt和libvncclient编写vnc的客户端程序,多线程读写,拒绝卡顿。
  • qt环境:5.15.3
  • libvncclient:0.9.14
  • 下载地址:https://github.com/LibVNC/libvncserver/releases

编译libvncclient

  • 打开CMakeList文件,找到编译开关,注释掉不需要的编译项目:
# all the build configuration switches
option(LIBVNCSERVER_INSTALL "Generate installation target" ON)
option(BUILD_SHARED_LIBS "Build shared libraries" ${UNIX})
option(WITH_ZLIB "Search for the zlib compression library to support additional encodings" ON)
option(WITH_LZO "Search for the LZO compression library to omit internal miniLZO implementation" ON)
option(WITH_JPEG "Search for the libjpeg compression library to support additional encodings" ON)
option(WITH_PNG "Search for the PNG compression library to support additional encodings" ON)
option(WITH_SDL "Search for the Simple Direct Media Layer library to build an example SDL vnc client" ON)
option(WITH_GTK "Search for the GTK library to build an example GTK vnc client" ON)
option(WITH_LIBSSHTUNNEL "Search for libsshtunnel to build an example ssh-tunneled client" ON)
option(WITH_THREADS "Search for a threading library to build with multithreading support" ON)
option(PREFER_WIN32THREADS "When searching for a threading library, prefer win32 threads if they are found" ON)
option(WITH_GNUTLS "Search for the GnuTLS secure communications library to support TLS" OFF)
option(WITH_OPENSSL "Search for the OpenSSL cryptography library to support TLS and use as crypto backend" ON)
option(WITH_SYSTEMD "Search for libsystemd to build with systemd socket activation support" ON)
option(WITH_GCRYPT "Search for Libgcrypt to use as crypto backend" ON)
option(WITH_FFMPEG "Search for FFMPEG to build an example VNC to MPEG encoder" ON)
option(WITH_TIGHTVNC_FILETRANSFER "Enable filetransfer if there is pthreads support" ON)
option(WITH_24BPP "Allow 24 bpp" ON)
option(WITH_IPv6 "Enable IPv6 Support" ON)
option(WITH_WEBSOCKETS "Build with websockets support" ON)
option(WITH_SASL "Build with SASL support" ON)
option(WITH_XCB "Build with XCB support" ON)
option(WITH_EXAMPLES "Build examples" OFF)
option(WITH_TESTS "Build tests" OFF)
option(WITH_QT "Build the Qt client example" OFF)
  • 也可以自己手动去掉不需要的库依赖,我这里没有把server的库依赖去干净。
  • 然后取出项目中的libvncclient.so和头文件中的client目录到自己的项目中。
  • 将build目录中的include中的rfbconfig.h拷贝到头文件目录

项目思路

  • 主要思路如下:
  • 创建一个主窗口QWidget用于画面渲染,创建一个接收线程和一个发送线程。
  • 接收线程负责读取vnc服务器发送的数据并解码装换成QImage,通过信号发送QImage,通知主线程刷新页面。
  • 发送线程用于发送主窗口的鼠标移动,点击等事件,用于实时更新操作。

项目编写

  • VncWideget : 主要的渲染窗口
#ifndef VNCVIEWWIDGET_H
#define VNCVIEWWIDGET_H

#include <QWidget>
#include <QThread>

#include "rfb/rfbclient.h"
#include "rfb/rfbconfig.h"

#include "vnc_client/vncrecvthread.h"
#include "vnc_client/vncsendworker.h"

class VncViewWidget : public QWidget
{
    Q_OBJECT
public:
    explicit VncViewWidget(QString ip, quint32 port, QWidget *parent = nullptr);
    ~VncViewWidget();

    void start();
    void stop();
    inline bool isStarted(){
        return _startFlag;
    }

    void updateImage(const QImage& image);

    void paintEvent(QPaintEvent *event) override;
    void mouseMoveEvent(QMouseEvent* event) override;
    void mousePressEvent(QMouseEvent *event) override;
    void mouseReleaseEvent(QMouseEvent *event) override;
    void closeEvent(QCloseEvent* event) override;

private:
    QImage _image;
    rfbClient *_cl;
    QString _ip;
    quint32 _port;
    bool _startFlag = false;

    QThread* _vncSendThread;
    VNCSendWorker* _vncSendWorker;
    VNCRecvThread* _vncRecvThread;

signals:
    void sendMouseState(rfbClient* cl, int x, int y, int button);
    void fullWindowCloseSignal();

public slots:
};

#endif // VNCVIEWWIDGET_H

  • VNCSendWorker:数据发送工作线程
#ifndef VNCSENDWORKER_H
#define VNCSENDWORKER_H

#include <QObject>

#include "rfb/rfbclient.h"

class VNCSendWorker : public QObject
{
    Q_OBJECT
public:
    explicit VNCSendWorker( QObject *parent = nullptr);

signals:

public slots:
    void sendMouseUpdateMsg(rfbClient* cl, int x, int y, int button);

};

#endif // VNCSENDWORKER_H

VNCRecvThread :接收线程

#ifndef VNCRECVTHREAD_H
#define VNCRECVTHREAD_H

#include <QThread>

#include <QImage>

#include "rfb/rfbclient.h"

class VNCRecvThread : public QThread
{
    Q_OBJECT
public:
    VNCRecvThread(QObject* parent = nullptr);

    inline void startRun(rfbClient* cl){
        if(_runFlag)return;
        _cl = cl;
        _cl->FinishedFrameBufferUpdate = frameBufferUpdated;
        rfbClientSetClientData(_cl, nullptr, this);
        _runFlag = true;
        this->start();
    }

    inline void stopRun(){
        if(!_runFlag)return;
        _runFlag = false;
        if(_cl)rfbClientSetClientData(_cl, nullptr, nullptr);
        if(_cl)_cl->FinishedFrameBufferUpdate = nullptr;
        _cl = nullptr;
    }

    static void frameBufferUpdated(rfbClient* cl);

protected:
    void run() override;

private:
    bool _runFlag = false;
    rfbClient* _cl;

signals:
    void updateImageSignal(QImage);
};

#endif // VNCRECVTHREAD_H

项目完整代码

gitee:https://gitee.com/li-gouhi2333/vncclient/tree/master/


网站公告

今日签到

点亮在社区的每一天
去签到