欧美成人精品手机在线观看_69视频国产_动漫精品第一页_日韩中文字幕网 - 日本欧美一区二区

LOGO OA教程 ERP教程 模切知識(shí)交流 PMS教程 CRM教程 開(kāi)發(fā)文檔 其他文檔  
 
網(wǎng)站管理員

使用libvncserver庫(kù)快速搭建VNC服務(wù)端

admin
2025年2月25日 11:11 本文熱度 850

文章目錄

  • VNC是什么

  • libvncserver的優(yōu)點(diǎn)和缺點(diǎn)

  • 構(gòu)建libvncserver

  • 使用libvncserver搭建VNCServer

  • X11模擬鼠標(biāo)鍵盤(pán)操作

  • libvncserver中處理鼠標(biāo)鍵盤(pán)消息

VNC是什么

VNC(Virtual Network Computing)是一種使用遠(yuǎn)程幀緩沖協(xié)議(RFB)的屏幕分享及遠(yuǎn)程操作軟件。VNC的服務(wù)端可以通過(guò)RFP協(xié)議將桌面視頻幀導(dǎo)出到互聯(lián)網(wǎng)上, 導(dǎo)出到互聯(lián)網(wǎng)上的視頻幀可以用VNC Client進(jìn)行訪問(wèn)。如果VNC Server開(kāi)啟了websockets, 除了VNC Viewer外 我們還可以通過(guò)瀏覽器內(nèi)的VNC查看器(如noVNC)來(lái)進(jìn)行連接訪問(wèn)。

VNC總體遵循C/S架構(gòu)。所以可以歸結(jié)以下幾點(diǎn):

  • VNC Server,共享被控機(jī)器的屏幕,以被動(dòng)的方式受VNC Client控制。

  • VNC Client, 有時(shí)候也稱為VNC Viewer,可以觀看服務(wù)端控制的屏幕, 遠(yuǎn)程操作服務(wù)端。

  • VNC協(xié)議,準(zhǔn)確來(lái)說(shuō)是RFB協(xié)議,沒(méi)有采用該協(xié)議的遠(yuǎn)程桌面就不叫VNC,該協(xié)議的目的非常簡(jiǎn)單,就是把一幀幀地把像素矩陣(坐標(biāo)系統(tǒng)是以左上角為原點(diǎn)的二維x,y坐標(biāo)系)和事件消息(鼠標(biāo)消息,鍵盤(pán)消息)從服務(wù)端傳送到客戶端。

libvncserver是一個(gè)開(kāi)源的VNC服務(wù)器端庫(kù),可以集成到C/C++應(yīng)用程序中,實(shí)現(xiàn)允許遠(yuǎn)程用戶通過(guò)VNC客戶端來(lái)顯示和控制本地計(jì)算機(jī)的功能。libvncserver提供了一些功能強(qiáng)大的API,可以方便地與其他應(yīng)用程序集成。它支持多個(gè)操作系統(tǒng)平臺(tái),包括Linux、Windows、Mac OS X和FreeBSD等,提供了多種VNC協(xié)議的實(shí)現(xiàn)。 使用libvncserver可以讓開(kāi)發(fā)人員方便地創(chuàng)建自己的VNC服務(wù)器,可用于遠(yuǎn)程桌面、遠(yuǎn)程支持、監(jiān)控等多種應(yīng)用場(chǎng)景。同時(shí),libvncserver還提供了一些高級(jí)功能,例如SFTP和SSH隧道,支持SSL加密 安全性較高。

libvncserver的優(yōu)點(diǎn)和缺點(diǎn)

libvncserver是一個(gè)功能強(qiáng)大的VNC服務(wù)器端庫(kù),具有如下優(yōu)點(diǎn):

  1. 開(kāi)源免費(fèi):libvncserver使用GPL許可證開(kāi)源,可以免費(fèi)使用,并可對(duì)其進(jìn)行修改和分發(fā)。

  2. 可移植性強(qiáng):libvncserver支持多個(gè)操作系統(tǒng)平臺(tái),包括Linux、Windows、Mac OS X和FreeBSD等,具有良好的可移植性。

  3. 靈活性好:libvncserver提供了一些功能強(qiáng)大的API,可以方便地與其他應(yīng)用程序集成,同時(shí)也支持多種VNC協(xié)議的實(shí)現(xiàn)。

  4. 高級(jí)功能完善:libvncserver提供了一些高級(jí)功能,比如SFTP和SSH隧道、SSL加密等,可以提高VNC的安全性。

但是,libvncserver也存在以下一些缺點(diǎn):

  1. 使用相對(duì)復(fù)雜:libvncserver是一個(gè)可編程的庫(kù),使用相對(duì)比較復(fù)雜,需要開(kāi)發(fā)者具有相關(guān)的編程經(jīng)驗(yàn)和技能。

  2. 社區(qū)相對(duì)小:相比其他類似的VNC服務(wù)器端庫(kù),libvncserver的社區(qū)規(guī)模相對(duì)較小,對(duì)于新手來(lái)說(shuō)可能學(xué)習(xí)起來(lái)較為困難。

  3. 適合大規(guī)模部署:由于libvncserver是一個(gè)VNC服務(wù)器端庫(kù),不能直接用于大規(guī)模的VNC部署,而需要結(jié)合其他工具或應(yīng)用程序來(lái)實(shí)現(xiàn)。

  4. 遠(yuǎn)程控制的粘貼板不支持復(fù)制粘貼Unicode文本,不能傳送任何除Latin-1 character set以外的字符集編碼。

  5. ?需要注意的一點(diǎn)就是libvncserver這個(gè)開(kāi)源VNC框架,還有很多BUG。

構(gòu)建libvncserver

項(xiàng)目地址:
https://github.com/LibVNC/libvncserver

# 下載代碼并構(gòu)建

git clone  https://github.com/LibVNC/libvncserver  

cd libvncserver

mkdir build

cd build

cmake ..

cmake --build .

使用libvncserver搭建VNCServer

//引用libvncserver  用于啟用服務(wù)端

#include <rfb/rfb.h>

#include <stdio.h>

#include <stdlib.h>

#include <algorithm>


//引用X11庫(kù)用于抓取桌面,模擬鼠標(biāo)鍵盤(pán)操作

#include <X11/Xlib.h>

#include <X11/Xutil.h>

#include <X11/extensions/Xfixes.h>


using namespace std;

static rfbCursorPtr myCursor;


//用于繪制鼠標(biāo)焦點(diǎn)

static const char* cur=

        "                   "

        " x                 "

        " xx                "

        " xxx               "

        " xxxx              "

        " xxxxx             "

        " xxxxxx            "

        " xxxxxxx           "

        " xxxxxxxx          "

        " xxxxxxxxx         "

        " xxxxxxxxxx        "

        " xxxxx             "

        " xx xxx            "

        " x  xxx            "

        "     xxx           "

        "     xxx           "

        "      xxx          "

        "      xxx          "

        "                   ";


static const char* mask=

        "xx                 "

        "xxx                "

        "xxxx               "

        "xxxxx              "

        "xxxxxx             "

        "xxxxxxx            "

        "xxxxxxxx           "

        "xxxxxxxxx          "

        "xxxxxxxxxx         "

        "xxxxxxxxxxx        "

        "xxxxxxxxxxxx       "

        "xxxxxxxxxx         "

        "xxxxxxxx           "

        "xxxxxxxx           "

        "xx  xxxxx          "

        "    xxxxx          "

        "     xxxxx         "

        "     xxxxx         "

        "      xxx          ";


//轉(zhuǎn)換像素?cái)?shù)據(jù)格式 要不顯示顏色異常

//XImage像素順序RGBA --> 轉(zhuǎn)frameBuffer像素順序BGRA

void copyImage(const XImage* image, char* buffer, int width, int height, int stride) 

{

    if((image == NULL) || (buffer == NULL))

    {

        return;

    }

    char* src = (char*) image->data;

 

    for(int index=0; index< width*height; ++index)

    {

char single_pixels[4];

memcpy(single_pixels,src+index*4, 4);

single_pixels[2]= (src+index*4)[0];

single_pixels[0]= (src+index*4)[2];

memcpy(buffer + index * 4, single_pixels, 4);

    }

}


//X11 默認(rèn)抓取的桌面內(nèi)容不帶鼠標(biāo)的光標(biāo), 需要單獨(dú)繪制鼠標(biāo)光標(biāo)

void paint_mouse_pointer(XImage *image, Display* display, int x_off, int y_off, unsigned int width, unsigned int height)

{

    Display *dpy = display;

    XFixesCursorImage *xcim;

    int x, y;

    int line, column;

    int to_line, to_column;

    int pixstride = image->bits_per_pixel >> 3;


    uint8_t *pix = (uint8_t*)image->data;


    /* Code doesn't currently support 16-bit or PAL8 */

    if (image->bits_per_pixel != 24 && image->bits_per_pixel != 32)

        return;


    xcim = XFixesGetCursorImage(dpy);


    x = xcim->x - xcim->xhot;

    y = xcim->y - xcim->yhot;


    to_line = min((y + xcim->height), (int)(height + y_off));

    to_column = min((x + xcim->width), (int)(width + x_off));


    for (line = max(y, y_off); line < to_line; line++) 

    {

        for (column = max(x, x_off); column < to_column; column++) 

        {

            int  xcim_addr = (line - y) * xcim->width + column - x;

            int image_addr = ((line - y_off) * width + column - x_off) * pixstride;

            int r = (uint8_t)(xcim->pixels[xcim_addr] >>  0);

            int g = (uint8_t)(xcim->pixels[xcim_addr] >>  8);

            int b = (uint8_t)(xcim->pixels[xcim_addr] >> 16);

            int a = (uint8_t)(xcim->pixels[xcim_addr] >> 24);


            if (a == 255) 

            {

                pix[image_addr+0] = r;

                pix[image_addr+1] = g;

                pix[image_addr+2] = b;

            } else if (a) {

                /* pixel values from XFixesGetCursorImage come premultiplied by alpha */

                pix[image_addr+0] = r + (pix[image_addr+0]*(255-a) + 255/2) / 255;

                pix[image_addr+1] = g + (pix[image_addr+1]*(255-a) + 255/2) / 255;

                pix[image_addr+2] = b + (pix[image_addr+2]*(255-a) + 255/2) / 255;

            }

        }

    }

    XFree(xcim);

    xcim = NULL;

}


//生成帶鼠標(biāo)光標(biāo)的桌面截圖

XImage* generateDesktopImageWithCursor(Display* display, Window root, int x, int y, unsigned int width, unsigned int height) 

{

     XImage* image = XGetImage(display, root, x, y, width, height, AllPlanes, ZPixmap);

     paint_mouse_pointer(image,display,x,y,width,height);

     return image;

}


int main(int argc, char** argv) 

{

    //開(kāi)啟桌面連接

    Display* disp = XOpenDisplay(NULL);

    if (!disp) 

    {

        printf("open x11 display error\n");

        exit(1);

    }

    //獲取桌面窗口

    Window root = DefaultRootWindow(disp);

    XWindowAttributes attrs;

    XGetWindowAttributes(disp, root, &attrs);


    //分配每一幀的內(nèi)存空間

    char* buffer = (char*) malloc(attrs.width * attrs.height * 4); // RGBA 格式

    if (!buffer) {

        printf("malloc buffer error \n");

        exit(1);

    }


    //使用 libvncserver 創(chuàng)建服務(wù)器

    rfbScreenInfoPtr server = rfbGetScreen(&argc, argv, attrs.width, attrs.height, 8, 3, 4);

    server->desktopName = "share desktop server ";

    server->frameBuffer = (char*) buffer;

    server->alwaysShared = true;


    //繪制客戶端移動(dòng)的光標(biāo)

    if(!myCursor) 

    {

        myCursor = rfbMakeXCursor( 19, 19, (char*) cur, (char*) mask);

    }


    server->cursor = myCursor;


    //初始化服務(wù)端

    rfbInitServer(server);


    while (true) 

    {

        //每100ms刷新一幀畫(huà)面內(nèi)容

        XImage* image = generateDesktopImageWithCursor(disp, root, 0, 0, attrs.width, attrs.height);

        copyImage(image, buffer, attrs.width, attrs.height, server->paddedWidthInBytes);

        rfbMarkRectAsModified(server, 0, 0, server->width, server->height);

        XDestroyImage(image);

        rfbProcessEvents(server, 100000); 

    }


    //清理緩存

    XCloseDisplay(disp);

    free(buffer);

    rfbShutdownServer(server, true);

    return 0;

}

在一臺(tái)機(jī)器上啟動(dòng)上面編寫(xiě)的VNC服務(wù)端,然后在另一臺(tái)機(jī)器上使用VNC-client(這里推薦VNC-Viewer)連接對(duì)應(yīng)機(jī)器的IP,就可以看到另外一臺(tái)機(jī)器上面的桌面了。 到這里我們就實(shí)現(xiàn)了服務(wù)端到客戶端的單向畫(huà)面?zhèn)鬏斄恕?下一步我們要接收客戶端發(fā)送過(guò)來(lái)的指令,并模擬對(duì)應(yīng)的鼠標(biāo)鍵盤(pán)操作。

X11模擬鼠標(biāo)鍵盤(pán)操作

Linux下接收到客戶端發(fā)送的指令之后,就需要模擬對(duì)應(yīng)的鼠標(biāo)鍵盤(pán)操作了,下面介紹一下如何使用X11庫(kù)模擬鼠標(biāo)鍵盤(pán)操作:

如果系統(tǒng)中沒(méi)有X11開(kāi)發(fā)庫(kù),可以通過(guò)下面的指令安裝:

sudo apt-get install libx11-dev libxext-dev libxtst-dev libxrender-dev libxmu-dev libxmuu-dev

//引用X11對(duì)應(yīng)的庫(kù)

#include <stdio.h>

#include <stdlib.h>

#include <X11/Xlib.h>

#include <X11/XKBlib.h>

#include <X11/extensions/XTest.h> 

#include <unistd.h>         

#include <termios.h>  


//獲取鼠標(biāo)的位置

bool GetMousePos(int& x, int& y)

{

Display *dpy;

Window root;

Window ret_root;

Window ret_child;

int root_x;

int root_y;

int win_x;

int win_y;

unsigned int mask;

dpy = XOpenDisplay(NULL);

root = XDefaultRootWindow(dpy);

if(XQueryPointer(dpy, root, &ret_root, &ret_child, &root_x, &root_y, &win_x, &win_y, &mask))

    {

x = root_x;

y = root_y;

return true;

}

return false;

}


//設(shè)置鼠標(biāo)的位置

bool SetMousePos(const int& x, const int& y){

Display *dpy = XOpenDisplay(0);

Window root = XRootWindow(dpy, 0);

XWarpPointer(dpy, None, root, 0, 0, 0, 0, x, y);

XFlush(dpy); 

    XCloseDisplay(dpy);

return true;

}


//模擬鼠標(biāo)左鍵按下

bool LeftPress(){

Display *display = XOpenDisplay(NULL);

XTestFakeButtonEvent(display, 1, true, 0);

XFlush(display);

XCloseDisplay(display);

return true;

}


//模擬鼠標(biāo)左鍵抬起

bool LeftRelease(){

Display *display = XOpenDisplay(NULL);

XTestFakeButtonEvent(display, 1, false, 0);

XFlush(display);

XCloseDisplay(display);

return true;

}


//模擬鼠標(biāo)右鍵按下

bool RightPress(){

Display *display = XOpenDisplay(NULL);

XTestFakeButtonEvent(display, 3, true, 0);

XFlush(display);

XCloseDisplay(display);

return true;

}


//模擬鼠標(biāo)右鍵抬起

bool RightRelease(){

Display *display = XOpenDisplay(NULL);

XTestFakeButtonEvent(display, 3, false, 0);

XFlush(display);

XCloseDisplay(display);

return true;

}


//模擬鼠標(biāo)中鍵按下

bool MiddlePress(){

Display *display = XOpenDisplay(NULL);

XTestFakeButtonEvent(display, 2, true, 0);

XFlush(display);

XCloseDisplay(display);

return true;

}


//模擬鼠標(biāo)中鍵抬起

bool MiddleRelease(){

Display *display = XOpenDisplay(NULL);

XTestFakeButtonEvent(display, 2, false, 0);

XFlush(display);

XCloseDisplay(display);

return true;

}


//模擬其它鍵按下

bool PressKey(int key){

Display *display = XOpenDisplay(NULL);

XTestFakeKeyEvent(display, XKeysymToKeycode(display, key), true, 0);

XFlush(display);

XCloseDisplay(display);

return true;

}


//模擬其它鍵抬起

bool ReleaseKey(int key){

Display *display = XOpenDisplay(NULL);

XTestFakeKeyEvent(display, XKeysymToKeycode(display, key), false, 0);

XFlush(display);

XCloseDisplay(display);

return true;

}


//獲取桌面寬度

bool GetScreenWidth(int& w){

Display* d = XOpenDisplay(NULL);

Screen* s = DefaultScreenOfDisplay(d);

w = s->width;

return true;

}


//獲取桌面高度

bool GetScreenHeight(int& h){

Display* d = XOpenDisplay(NULL);

Screen* s = DefaultScreenOfDisplay(d);

h = s->height;

return true;

}


//判斷是否有組合鍵按下

bool KeyIsDown(int& key){

XkbStateRec r;

    Display* d = XOpenDisplay(NULL);

    XkbGetState(d, XkbUseCoreKbd, &r);

if((r.mods & 0x01) && key == 16) //Shift

return true;

if((r.mods & 0x04) && key == 17) //Ctrl

return true;

if((r.mods & 0x08) && key == 18) //Alt

return true;

    XCloseDisplay(d);

return false;

}

libvncserver中處理鼠標(biāo)鍵盤(pán)消息

定義完成模擬鼠標(biāo)鍵盤(pán)操作的函數(shù)之后,我們就可以在VNCServer中接收鼠標(biāo)鍵盤(pán)消息然后模擬操作了,對(duì)應(yīng)的處理流程如下所示:


//鼠標(biāo)消息處理

void mouseevent(int buttonMask, int x, int y, rfbClientPtr cl) 

{

static int oldButtonMask = 0;

SetMousePos(x, y);


if(buttonMask && !oldButtonMask)

{

if(buttonMask == 1)

LeftPress();

if(buttonMask == 2)

MiddlePress();

if(buttonMask == 4)

RightPress();

if(buttonMask == 8)

WheelUp();

if(buttonMask == 16)

WheelDown();

}


if(!buttonMask && oldButtonMask){

if(oldButtonMask == 1)

LeftRelease();

if(oldButtonMask == 2)

MiddleRelease();

if(oldButtonMask == 4)

RightRelease();

}

oldButtonMask = buttonMask;

}


//處理按鍵消息

void keyevent(rfbBool down, rfbKeySym key, rfbClientPtr cl) 

{

if(down){

PressKey(key);

}

else {

ReleaseKey(key);

}

}



int main(int argc, char** argv) 

{

    //省略重復(fù)代碼

    //使用 libvncserver 創(chuàng)建服務(wù)器

    rfbScreenInfoPtr server = rfbGetScreen(&argc, argv, attrs.width, attrs.height, 8, 3, 4);

    server->desktopName = "share desktop server ";

    server->frameBuffer = (char*) buffer;

    server->alwaysShared = true;

    server->alwaysShared = true;


    //注冊(cè)鼠標(biāo)鍵盤(pán)消息的回調(diào)函數(shù)

server->ptrAddEvent = mouseevent;

server->kbdAddEvent = keyevent;


    //省略重復(fù)代碼

    return 0;

}

通過(guò)上面的處理我們就可以搭建一個(gè)基本的VNC服務(wù)端了,該服務(wù)端能完成基本的遠(yuǎn)程控制指令。如果想進(jìn)一步深度優(yōu)化,可以參考其它的VNC開(kāi)源項(xiàng)目比如: TigerVNC、UltraVNC、TightVNC、RealVNC。


該文章在 2025/2/25 11:16:05 編輯過(guò)
關(guān)鍵字查詢
相關(guān)文章
正在查詢...
點(diǎn)晴ERP是一款針對(duì)中小制造業(yè)的專業(yè)生產(chǎn)管理軟件系統(tǒng),系統(tǒng)成熟度和易用性得到了國(guó)內(nèi)大量中小企業(yè)的青睞。
點(diǎn)晴PMS碼頭管理系統(tǒng)主要針對(duì)港口碼頭集裝箱與散貨日常運(yùn)作、調(diào)度、堆場(chǎng)、車隊(duì)、財(cái)務(wù)費(fèi)用、相關(guān)報(bào)表等業(yè)務(wù)管理,結(jié)合碼頭的業(yè)務(wù)特點(diǎn),圍繞調(diào)度、堆場(chǎng)作業(yè)而開(kāi)發(fā)的。集技術(shù)的先進(jìn)性、管理的有效性于一體,是物流碼頭及其他港口類企業(yè)的高效ERP管理信息系統(tǒng)。
點(diǎn)晴WMS倉(cāng)儲(chǔ)管理系統(tǒng)提供了貨物產(chǎn)品管理,銷售管理,采購(gòu)管理,倉(cāng)儲(chǔ)管理,倉(cāng)庫(kù)管理,保質(zhì)期管理,貨位管理,庫(kù)位管理,生產(chǎn)管理,WMS管理系統(tǒng),標(biāo)簽打印,條形碼,二維碼管理,批號(hào)管理軟件。
點(diǎn)晴免費(fèi)OA是一款軟件和通用服務(wù)都免費(fèi),不限功能、不限時(shí)間、不限用戶的免費(fèi)OA協(xié)同辦公管理系統(tǒng)。
Copyright 2010-2025 ClickSun All Rights Reserved