小男孩‘自慰网亚洲一区二区,亚洲一级在线播放毛片,亚洲中文字幕av每天更新,黄aⅴ永久免费无码,91成人午夜在线精品,色网站免费在线观看,亚洲欧洲wwwww在线观看

分享

VNC源碼閱讀

 我是小丑1 2011-08-09

VNC源碼閱讀--VNC圖像更新機制  

2010-09-25 17:20:41|  分類: 默認(rèn)分類 |  標(biāo)簽: |字號 訂閱

VNC源碼閱讀--VNC圖像更新機制
2009-09-29 14:33

VNC的圖像更新機制核心為,桌面區(qū)域更新記錄策略和更新區(qū)域通知策略。桌面更新區(qū)域記錄主要是通過hooks記錄桌面上變化的矩形區(qū)域,只記錄更新的矩形區(qū)不記錄具體更新的數(shù)據(jù)。更新區(qū)域記錄步驟大致如下:1.wm_hooks截獲桌面變化的相關(guān)消息,并轉(zhuǎn)化為自定義的消息發(fā)送給WMHooksThread線程處理。 2. WMHooksThread 中用SimpleUpdateTracker new_changes記錄新的更新區(qū)域.3.把SimpleUpdateTracker new_changes更新拷貝到SDisplay中。4.每次要發(fā)送桌面更新的時候,把SDisplay中記錄的更新區(qū)域傳給VNCServerST 對象中。更新區(qū)域的通知主要有poll和push兩種機制。push是服務(wù)器每隔10ms檢查有沒有更新,如果有更新則主動把更新推送給客戶端,poll機制則是客戶端主動請求更新,客戶端通過發(fā)送framebufferupdate請求某一個區(qū)域更新,服務(wù)器處理該消息發(fā)送相應(yīng)的更新。詳細分析如下:

1.Wm_hooks截獲消息并轉(zhuǎn)化為自定義的消息發(fā)送給WMHooksThread線程處理。

Wm_hooks自定義的消息:

UINT WM_HK_WindowChanged = RegisterWindowMessage(_T("RFB.WM_Hooks.WindowChanged"));

UINT WM_HK_WindowClientAreaChanged = UINT WM_HK_WindowBorderChanged = RegisterWindowMessage(_T("RFB.WM_Hooks.WindowBorderChanged"));

UINT WM_HK_RectangleChanged = RegisterWindowMessage(_T("RFB.WM_Hooks.RectangleChanged"));

UINT WM_HK_CursorChanged = RegisterWindowMessage(_T("RFB.WM_Hooks.CursorChanged"));

鉤子截獲到消息以后,把它轉(zhuǎn)化為自定義的消息,然后發(fā)送給WMHooksThread線程處理,消息轉(zhuǎn)化如下:

邊框更新消息:WM_NCPAINT,WM_NCACTIVATE

客戶區(qū)域更新消息:BM_SETCHECK, BM_SETSTATE,EM_SETSEL,WM_CHAR,WM_ENABLE,WM_KEYUP,WM_LBUTTONUP,WM_MBUTTONUP,WM_PALETTECHANGED,WM_RBUTTONUP,WM_SYSCOLORCHANGE,WM_SETTEXT。

窗口改變消息:WM_HSCROLL,WM_VSCROLL,482,485。

矩形區(qū)更新消息:WM_DESTROY

窗口客戶區(qū)消息:WM_PAINT

鼠標(biāo)消息:WM_NCMOUSEMOVE,WM_MOUSEMOVE

2 . WMHooksThread 中用SimpleUpdateTracker new_changes記錄新的更新區(qū)域

WMHooksThread::run() 函數(shù)中先判斷出矩形區(qū)域改變的大小,然后調(diào)用NotifyHooksRegion(const Region& r)把改變的區(qū)域記錄到SimpleUpdateTracker new_changes中。

NotifyHooksRegion(const Region& r) {

Lock l(hook_mgr_lock);

std::list<WMHooks*>::iterator i;

for (i=hooks.begin(); i!=hooks.end(); i++) {

    (*i)->new_changes.add_changed(r);

    if (!(*i)->notified) {

      (*i)->notified = true;

      PostMessage((*i)->getHandle(), WM_USER, 0, 0); // 把消息通知到clipper見下面一個處理函數(shù)

    }

}

}

3.把更新區(qū)域拷貝到SDisplay中

rfb::win32::WMHooks::processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {

switch (msg) {

case WM_USER:

    {

      Sleep(0);

      Lock l(hook_mgr_lock);

      notified = false;

      new_changes.get_update(*clipper); //把更新通知到clipper中

      new_changes.clear();

    }

    break;

}

return MsgWindow::processMessage(msg, wParam, lParam);

}

Cliper在下面設(shè)置

rfb::win32::WMHooks::setUpdateTracker(UpdateTracker* ut) {

if (clipper) delete clipper;

clipper = new ClippedUpdateTracker(*ut);

clipper->set_clip_region(clip_region);

return AddHook(this);

}

UpdateTracker* ut 為void SDisplay::start(VNCServer*vs)中設(shè)置 core->using_hooks = core->wm_hooks.setUpdateTracker(this);

4.把SDisplay中記錄的數(shù)據(jù)傳給VNCServerST 對象

在 SDisplay::processEvent(HANDLE event) {

try_update = flushChangeTracker() || try_update; //把變化的區(qū)域拷貝到VNCServerST中

      if (try_update)

        server->tryUpdate();          //把更新發(fā)送給服務(wù)器

}

flushChangeTracker()實現(xiàn)如下:

bool SDisplay::flushChangeTracker() {

if (change_tracker.is_empty())

    return false;

change_tracker.translate(screenRect.tl.negate());

change_tracker.get_update(*server); //server 實際指向VNCServerST 對象該函數(shù)把SDisplay中的更新拷貝到VNCServerST中。

change_tracker.clear();

return true;

}

兩種數(shù)據(jù)更新方式:Push機制和Pull機制

Push:

SdisplayCore 中IntervalTimer cursorTimer定時器,每隔10ms嘗試著檢查一下是否有更新,如果有更新就發(fā)送更新給客戶端。

第一步:

LRESULT SDisplayCore::processMessage(UINT msg, WPARAM wParam, LPARAM lParam) {

case TIMER_CURSOR:

     display->triggerUpdate(); //SDisplay* display;

}

第二步:

void SDisplay::triggerUpdate() {

     if (core)

         SetEvent(updateEvent); //使事件對象為受信狀態(tài)

}

第三步:

SDisplay::processEvent(HANDLE event) {

     if (event == updateEvent) {

         if (try_update)

                   server->tryUpdate(); // VNCServer* server指針 指向子類VNCServerST

}

}

第四步:向每一個連接的客戶端發(fā)送更新

void VNCServerST::tryUpdate()

{

     std::list<VNCSConnectionST*>::iterator ci, ci_next;

     for (ci = clients.begin(); ci != clients.end(); ci = ci_next) {

         ci_next = ci; ci_next++;

         (*ci)->writeFramebufferUpdateOrClose();

     }

}

第五步:

void VNCSConnectionST::writeFramebufferUpdateOrClose()

{

     try {

         writeFramebufferUpdate();

     } catch(rdr::Exception &e) {

         close(e.str());

     }

}

第六步:SimpleUpdateTracker updates對象記錄更新的區(qū)域,如果屏幕有更新則發(fā)送更新

void VNCSConnectionST::writeFramebufferUpdate(){

if (!update.is_empty() || writer()->needFakeUpdate() || drawRenderedCursor) {

         int nRects = update.numRects() + (drawRenderedCursor ? 1 : 0);

         writer()->writeFramebufferUpdateStart(nRects);

         Region updatedRegion;

         writer()->writeRects(update, &image_getter, &updatedRegion); // SmsgWriter *

         updates.subtract(updatedRegion);

         if (drawRenderedCursor)

              writeRenderedCursorRect();

         writer()->writeFramebufferUpdateEnd();

         requested.clear();

     }

}

第七步:利用RFB協(xié)議發(fā)送更新

void SMsgWriterV3::writeFramebufferUpdateStart(int nRects)

{

     startMsg(msgTypeFramebufferUpdate);

     os->pad(1);

     if (wsccb) nRects++;

     if (needSetDesktopSize) nRects++;

     os->writeU16(nRects);

     nRectsInUpdate = 0;

     nRectsInHeader = nRects;

     if (wsccb) {

         wsccb->writeSetCursorCallback();

         wsccb = 0;

     }


    本站是提供個人知識管理的網(wǎng)絡(luò)存儲空間,所有內(nèi)容均由用戶發(fā)布,不代表本站觀點。請注意甄別內(nèi)容中的聯(lián)系方式、誘導(dǎo)購買等信息,謹(jǐn)防詐騙。如發(fā)現(xiàn)有害或侵權(quán)內(nèi)容,請點擊一鍵舉報。
    轉(zhuǎn)藏 分享 獻花(0

    0條評論

    發(fā)表

    請遵守用戶 評論公約

    類似文章 更多