基於通訊端通訊的遠程截屏顯示與控制技術

來源:互聯網
上載者:User

摘 要:採用Socket通訊端通訊,使用MFC與SDK混合編程技術,完成遠程截取目標機螢幕並實現本地機對目標機的控制功能。其中,本地機介面使用MFC,目標機使用SDK,這種實現方案既方便本地機作為用戶端控制介面的實現,同時又滿足目標機作為服務端無需介面、僅實現Socket通訊的要求。

關鍵詞:WinSocket;通訊端通訊;遠端控制;截屏

Display and Control of Remote Obtaining Screen Based on Socket Communication
ZHONG Wen, YU Xinsheng
(Embedded System Dept., East China Institute of Computer Technology, Shanghai 200233)
【Abstract】Based on the Socket communication, this paper uses the program technology of MFC and SDK to obtain the remote machine’s screen and realize the control function. In the paper, the interface of client use MFC, and the server use SDK, this design can realize the interface of client expediently, and adapt for the requirement that the server not need interface but socket communication.
【Key words】WinSocket; Socket communication; Remote control; Obtaining screen

遠端控制技術在遠程裝置(軟體)的維護、監控與故障診斷等方面有廣泛的應用前景,且大都使用Client/Server模式。該結構包括串連在網路中的多台電腦,那些處理應用、請求另一電腦服務的電腦為客戶機(本地機),而響應請求並處理請求的電腦稱為伺服器(目標機)。
遠端控制的原理[1]是:使用者串連到網路上,客戶程式發送身分識別驗證資訊和與遠程主機串連的請求,遠程主機的伺服器端程式驗證客戶身份,若驗證通過,就與客戶建立串連,並向使用者發送驗證通過和已建立串連的資訊。此時使用者便可以通過用戶端程式向遠程主機發送要執行的指令,而伺服器端程式則執行這些指令,並把鍵盤、滑鼠和螢幕重新整理傳給用戶端程式,用戶端程式通過處理把主機螢幕等資訊進行顯示,使使用者就像親自在遠程主機上操作一樣。這種方式稱為基於遠程服務的遠端控制(Remote Control over Remote Service)。
綜上所述,實現用戶端對服務端的遠端控制,需要就解決雙機Socket網路通訊、遠程截取螢幕顯示以及螢幕資料傳送控制等3個問題進行討論。

1 雙機Socket網路通訊[2]

初始化服務端Socket:在調用Socket前先要初始化,即載入相應版本的DLL,通過調用WSAStartup函數,將載入成功的Socket庫版本的相關資訊填在LPWSADATA結構中;
WSADATA lpWSAData;
WSAStartup(MAKEWORD(1,1),&lpWSAData);
建立服務端Socket:完成初始化之後,調用socket函數建立一個通訊端,返回通訊端控制代碼,在其後通訊中始終用來標識通訊端,若調用失敗則返回INVALID_SOCKET;
SOCKET sktConnect=socket(AF_INET,SOCK_STREAM,0);
綁定服務端地址:在為某種特定協議建立了通訊端後,就用bind函數將通訊端綁定到一個本機地址,其類型是sockaddr,用於指明通訊端綁定地址,包括IP地址與連接埠號碼;
bind(sktConnect,(struct sockaddr far *)&sockaddrin,sizeof(sockaddrin));
服務端監聽網路:socket利用listen函數設定狀態位,用來檢測是否有到來的串連請求,然後調用accept函數,準備接收用戶端串連訊號,無串連請求時,服務進程被阻塞;

listen(sktConnect,1);
sktClient=accept(sktConnect,(struct sockaddr far *)&sockaddrin,& sockaddrlen);

初始化與建立用戶端Winsock:首先利用AfxSocketInit函數判斷參數lpwsaData是否為空白,從而確定是否調用WSAStartup函數來填充WSADATA結構,隨後同樣調用socket函數建立用戶端的通訊端,給用戶端Sockaddr_in結構賦值,地址類型和連接埠號碼與服務端相同;
通訊端選項設定:使用setsockopt函數設定通訊端選項,比如發送或者接收的逾時設定,緩衝區的容量設定,使用ioctlsocket函數設定socket的I/O模式等;

int ret=ioctlsocket(sktClient,FIONBIO,(unsigned long*)&ul);

雙方建立串連:用戶端調用connect函數向服務端發出串連請求,當串連請求到來時,被阻塞服務端的accept函數產生一個新的位元組流通訊端,返回用戶端Sockaddr_in結構變數,用帶有用戶端地址的通訊端與用戶端進行串連,然後向用戶端返回接收訊號;
connect(sktClient,(const struct sockaddr *)&sockaddrin,sizeof (sockaddrin));
收發資料:一旦用戶端通訊端接收到來自服務端的接受訊號,則表示雙方已經實現串連,任何一方均可使用Send/Write函數和Recv/Read函數向對方發送或者接收資料;
send(sktClient,chrSend,10,0);recv(sktClient,chrReceive,10,0);

關閉通訊端與winsock登出:服務端和用戶端可以通過調用closesocket函數關閉通訊端上的所有發送和接收操作,撤銷通訊端並且中斷串連。同時,winsock服務的動態連結程式庫在使用結束後,應用程式必須調用WSACleanup函數將其登出,並釋放分配的資源。
Winsock通訊端主要工作流程1,①~⑩標識網路資料交換順序。

圖1 Winsock通訊端主要工作流程

2 遠程截取螢幕顯示

服務端在接收到用戶端的螢幕資料請求後,通過使用當前螢幕裝置的控制代碼,開始向開闢的記憶體地區複製螢幕資料,得到與裝置相關的GDI位元影像;然後再通過設定位元影像資訊頭、調色盤等,最後得到與裝置無關的DIB位元影像。

2.1擷取當前螢幕的裝置相關位元影像[3](DDB)

裝置相關位元影像(DDB)也稱為圖形裝置介面(GDI)位元影像,在MFC庫中用CBitmap類來儲存。該對象包含與裝置相關的GDI模組資料結構。應用程式在截獲螢幕顯示資料的時候,將資料填充到開闢的相容性記憶體地區中,並與CBitmap對象的控制代碼建立關聯,從而得到GDI位元影像資料的備份。但由於GDI位元影像中關於位的安排完全依賴於顯示裝置,在不同類型電腦間傳遞GDI位元影像是沒有意義的。所以還需要進一步轉化,得到裝置無關位元影像DIB。

(1)得到當前螢幕的解析度,從而確定截取螢幕的範圍;
ScreenX=GetSystemMetrics(SM_CXSCREEN);
ScreenY=GetSystemMetrics(SM_CYSCREEN);

(2)得到螢幕HDC,並開闢相容性記憶體地區,建立相容性的HBITMAP;
HDC hdcmy=CreateDC("DISPLAY",NULL,NULL, NULL);
HDC hbufdc=CreateCompatibleDC(hdcmy);
HBITMAP hBit=CreateCompatibleBitmap(hdcmy, ScreenX,ScreenY);

(3)將當前螢幕內容複寫到之前開闢的記憶體地區中,得到當前螢幕的GDI位元影像;
HBITMAP hOldBitmap=(HBITMAP)SelectObject(hbufdc,hBit);
StretchBlt(hbufdc,0,0,ScreenX,ScreenY,hdcmy,0,0,ScreenX,ScreenY,SRCCOPY);
hBit=(HBITMAP)SelectObject(hbufdc,hOldBitmap);

2.2轉化裝置相關位元影像(DDB)至裝置無關位元影像[3](DIB)

DIB內建顏色資訊,可以實現調色盤管理,任何運行Windows的電腦中都可以處理這種標準的位元影像格式,BMP檔案中就包含了一個DIB,主要由位元影像檔案頭、位元影像資訊頭、調色盤和DIB映像資料4個部分組成,DDB向DIB的轉化實際上就是利用DDB中包含的映像資訊,填充DIB除位元影像檔案頭的另外3個部分,從而得到與裝置無關的位元影像資料。最後可再通過添加位元影像檔案頭,構成一幅標準的BMP映像。

(1)通過BITMAP控制代碼hBit,得到位元影像資訊,隨後填充BITMAPINFOHEADER結構,計算InfoHeader長度,初始化調色盤,最後分配儲存空間存放上述資訊頭與調色盤資料;
GetObject(hBit,sizeof(bitmap),(LPSTR)&bitmap);
int ncolors=1<<(bitmap.bmPlanes*bitmap.bmBitsPixel);
DWORD dwLen=sizeof(BITMAPINFOHEADER)+ncolors*sizeof (RGBQUAD);
HANDLE hDib=GlobalAlloc(GMEM_FIXED,dwLen);

(2)計算位元影像資料實際佔用的位元組數,使其寬度大於或者等於離4最近的整數倍,修正原biSizeImage數值,然後重新計算並分配空間用於儲存資訊頭,調色盤和實際映像資料;
bi.biSizeImage=((((bi.biWidth*bi.biBitCount)+31)&~31)/8)*bi.biHeight;
dwLen += bi.biSizeImage;
if(handle=GlobalReAlloc(hDib,dwLen,GMEM_MOVEABLE)) hDib=handle;
(3)向開闢的指定儲存地區中複製上述資訊頭、調色盤以及實際映像資訊3部分資料,最後返回該儲存地區的控制代碼,得到最終的DIB位元影像;
LPBITMAPINFOHEADER lpbi=(LPBITMAPINFOHEADER)hDib;
GetDIBits( hdc, bitmap,0L,(DWORD)bi.biHeight,(LPBYTE)lpbi +(bi.biSize+ncolors
*sizeof(RGBQUAD)),(LPBITMAPINFO)lpbi,(DWORD)DIB_RGB_COLORS);

3 螢幕資料傳送控制

螢幕資料的傳送控制主要在如何確認服務端與用戶端之間的串連,服務端如何定時分塊發送螢幕資料,用戶端如何拼接螢幕資料並顯示映像,服務端如何響應用戶端的滑鼠事件等幾個方面。

3.1服務端與用戶端的串連確認
雙方串連可以由用戶端指定服務端IP地址,或者在子網段內發送通訊對方標識,服務端接收到該標識後,向用戶端發送確認標識,用戶端收到確認資訊後,表明雙方實現串連。
以下代碼為用戶端程式片斷,服務端程式將發送和接收函數的順序對調即可。

char cFlag[8]="CopyScr/0";
send(sktClient,cFlag,8,0);//發送client端標誌
recv(sktClient,cFlag,8,0);//接收server端標誌

3.2服務端定時分塊發送螢幕資料
用戶端以某一定時器設定為間隔,向服務端請求螢幕資料,服務端收到請求後,首先擷取當前螢幕的GDI位元影像資料,並轉化為DIB位元影像資料,隨後採用分塊傳送的方式,向用戶端發送螢幕的位元影像資料,分塊過程如下所示:

(1)發送螢幕位元影像資料的相關資訊,諸如尺寸、長度、高度等資訊至用戶端;
send(sktClient,(char*)&ScrInfo,sizeof(ScrInfo)+1,0);

(2)分塊發送DIB位元影像資料,以SENDBLOCK為分塊尺寸,同時調整當前資料指標位置;
LPBYTE plmagePoint=(LPBYTE)hDib;
for(WORD i=0;i<(ScrInfo.dwSize/SENDBLOCK);i++){
send(sktClient,(char*)plmagePoint,sizeof(BYTE)*SENDBLOCK,0);
plmagePoint=plmagePoint + SENDBLOCK;
recv(sktClient,(char*)&StopFlag,sizeof(int)+1,0);}

(3)當螢幕位元影像資料不是剛好等於分塊尺寸倍數的時候,用於處理餘下的資料傳送;
if (ScrInfo.dwSize %SENDBLOCK)
send(sktClient,(char*)plmagePoint,ScrInfo.dwSize%SENDBLOCK,0);

3.3用戶端拼接螢幕資料並顯示映像
用戶端的螢幕資料拼接程式,剛好與服務端的螢幕資料切分程式相對應,首先是接收螢幕位元影像相關資訊,然後按照指定的分塊大小接收螢幕資料,最後將小於分塊尺寸的螢幕資料單獨進行接收處理,得到服務端完整的一次螢幕資料,位元影像採用StretchDIBits函數顯示。
StretchDIBits(dc,0,0,rect.right,rect.bottom,0,0,
((LPBITMAPINFOHEADER)SvrData)->biWidth,
((LPBITMAPINFOHEADER)SvrData)->biHeight,
(LPBYTE)SvrData+(sizeof(BITMAPINFOHEADER)+color*sizeof(RGBQUAD)),
(LPBITMAPINFO)SvrData,DIB_RGB_COLORS,SRCCOPY);

3.4服務端響應用戶端的滑鼠事件
當使用滑鼠點擊用戶端中顯示服務端當前螢幕的地區,用戶端程式將會記錄下具體的左/右鍵,單/雙擊,X/Y座標位置等資訊,作為滑鼠事件發送給服務端,服務端隨後進行解析,並作出相應的響應,從而實現用戶端得到服務端螢幕並加以控制的功能。
mouse_event(MOUSEEVENTF_LEFTDOWN ,0,0,0,GetMessageExtraInfo());

4 結論

通過上述方式,用戶端可以定時接收服務端當前的螢幕資訊,同時服務端也可以對用戶端的滑鼠事件作出響應,從而實現本地機對目的機的遠端控制。本顯示控制技術已經被成功應用於電子測量儀器的遠程監控系統中。
參考文獻
1 常永昌, 馮新喜, 王 芳. 一種遠端控制軟體的設計與實現[J]. 電腦應用, 2003, 23 (3).
2 鄭靈翔, 洪景新. Windows 2000/XP下原始通訊端的編程與應用[J]. 微型機與應用, 2002, 21(6).
3 何 斌, 馬天予, 王運堅等. Visual C++數位影像處理(第2版). 北京:人民郵電出版社, 2002-12.

聯繫我們

該頁面正文內容均來源於網絡整理,並不代表阿里雲官方的觀點,該頁面所提到的產品和服務也與阿里云無關,如果該頁面內容對您造成了困擾,歡迎寫郵件給我們,收到郵件我們將在5個工作日內處理。

如果您發現本社區中有涉嫌抄襲的內容,歡迎發送郵件至: info-contact@alibabacloud.com 進行舉報並提供相關證據,工作人員會在 5 個工作天內聯絡您,一經查實,本站將立刻刪除涉嫌侵權內容。

A Free Trial That Lets You Build Big!

Start building with 50+ products and up to 12 months usage for Elastic Compute Service

  • Sales Support

    1 on 1 presale consultation

  • After-Sales Support

    24/7 Technical Support 6 Free Tickets per Quarter Faster Response

  • Alibaba Cloud offers highly flexible support services tailored to meet your exact needs.