基于套接字通信的远程截屏显示与控制技术

基于套接字通信的远程截屏显示与控制技术

钟 文,余新胜
(华东计算技术研究所嵌入系统部,上海 200233)

摘 要:采用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


网友们的有用的评论
文章介绍的只是远程屏幕传输原理性的东西,不知道作者实际做出的效果如何,但是据我以前的实践,至少存在以下几个问题:
1.数据量过大。如果以24位图为例,每秒更新一次,则每秒需要发送1024*768*3=2.25M的数据量,在一般的网络内基本上都是达不到的,因此必须采用好的实时压缩算法
2.画面不流畅。虽然采用分块算法,但是仍然需要传输整屏数据,正确的做法应该是采用热点跟踪,只传输变化的部分
3.屏幕传输和鼠标键盘动作应该分开,采用多线程
另外, mouse_event已经不提倡使用,最好用SendInput替换
当然,这里不是批评作者,能写文章跟大家共享是一种很好的美德。大家共同学习~ ( bigshow 发表于 2008-5-30 20:46:00)


我最近也在做这个,用的是驱动解屏(不是自己写的),只取变化的区域传输,目前正在完善传输部分,截图比较快,可以交流一下, ( semonping 发表于 2008-6-9 22:34:00)

大家delphi盒子上去看看,那上面有好几个代码
XOR 差异传输,基于消息hook获取变化窗口,分块隔行扫描,隔行扫描,变矩形隔行扫描,mirror驱动,这是目前常用的算法。值得一提的是很多木马比如黑 洞,灰鸽子,zxshell的屏幕传输算法都非常优秀,它们和俄罗斯远控redmin早期版本一样,都是隔行扫描算法。相应的开源代码也很多,有兴趣的人 可以去收集些 ( xicao 发表于 2008-6-9 16:29:00)

xicao,可以和你交流下吗?我觉得这方面的资料很少很少要做只有自己努力了,所以大家都讨论下,可以吧? ( w2872 发表于 2008-6-9 15:34:00)

我在远控中常用的方法是:
1.XOR差异传输+zlib压缩,数据量小,但是占用CPU大
2.隔行扫描算法+zlib压缩,传输快,几乎不占用CPU,缺点是碎片多,网速差的情况下不理想 ( xicao 发表于 2008-6-9 12:13:00)

  • 0
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
### 回答1: 设计和实现基于 HarmonyOS 的视频播放器需要以下接口: 1. 加载视频文件:该接口用于加载视频文件,可以接受本地文件路径或远程 URL 作为参数。 2. 播放控制:该接口用于控制视频的播放、暂停、快进、快退等操作。该接口还应提供获取当前播放状态和播放位置的方法。 3. 音量控制:该接口用于控制视频的音量大小,可以实现静音、增大或减小音量等操作。 4. 屏幕旋转控制:该接口用于控制视频播放时屏幕的旋转,可以实现自动旋转、强制横屏或竖屏等操作。 5. 弹幕控制:该接口用于控制弹幕的显示和隐藏,可以实现添加、删除弹幕等操作。 6. 播放列表:该接口用于管理播放列表,可以实现添加、删除、切换视频等操作。 7. 视频信息:该接口用于获取视频的基本信息,如视频时长、分辨率、帧率等。 8. 高级设置:该接口用于实现一些高级功能,如画面比例、字幕控制、多音轨切换等。 9. 错误处理:该接口用于处理视频播放过程中出现的错误,可以提供错误码和错误信息。 10. 事件监听:该接口用于注册和监听视频播放过程中的各种事件,如播放开始、播放结束、缓冲进度等。 以上是设计和实现基于 HarmonyOS 的视频播放器需要的接口,根据具体需求,还可以根据需要添加其他接口。 ### 回答2: 设计和实现一个基于HarmonyOS的视频播放器,需要以下几种关键的接口: 1. 初始化接口:提供一个初始化接口来设置播放器的初始配置,例如音量、亮度、画面质量等。 2. 播放控制接口:包括开始播放、暂停、停止、快进、快退等基本的播放控制功能。 3. 媒体源接口:通过该接口可以设置播放的媒体源,可以是本地文件、远程URL、流媒体等不同的媒体源。 4. 进度控制接口:提供接口来获取当前播放的位置和总时长,以及设置特定的播放位置。 5. 声音控制接口:通过接口可以调整播放器的音量大小、静音状态等。 6. 字幕控制接口:提供接口来加载和控制字幕的显示,包括字幕的颜色、字体大小、位置等。 7. 截屏与录制接口:提供截屏和录制视频的功能接口,可以将当前播放的画面保存为图片或视频文件。 8. 异常处理接口:处理各种异常情况,例如网络连接异常、媒体文件损坏等,并提供异常处理的回调接口。 9. UI控制接口:提供接口来控制播放器界面的显示和交互,包括播放按钮、进度条、全屏切换等。 通过以上接口的设计和实现,基于HarmonyOS的视频播放器可以提供丰富的功能和灵活的操作方式,以满足用户对视频播放的多样化需求。 ### 回答3: 设计和实现基于HarmonyOS的视频播放器需要以下接口: 1. 播放控制接口:包括开始播放、暂停、继续播放、停止、快进和快退等功能。这些接口允许用户对视频进行常用的播放控制操作。 2. 音频控制接口:允许用户对视频的音量进行调节,包括增加和减少音量的功能。此外,还需要支持静音操作。 3. 进度控制接口:提供了获取视频当前播放进度、跳转到指定时间点以及获取视频总时长的接口。用户可以根据需要进行进度控制。 4. 媒体信息接口:提供获取视频的基本信息,例如标题、作者、封面等。这些信息可以显示在播放界面上,提供更好的用户体验。 5. 媒体列表接口:支持用户创建媒体播放列表,并提供增加、删除、获取和清空媒体列表的接口。用户可以根据需求自定义播放顺序或者切换不同的播放内容。 6. 画面控制接口:允许用户对视频画面进行控制,包括调整亮度、对比度、饱和度等参数,以及切换不同的画面模式(如全屏、窗口等)。 7. 网络传输接口:支持通过网络加载和播放在线视频。提供接口以便用户可以输入视频链接或者通过搜索来获取在线视频资源并进行播放。 8. 错误处理接口:提供了对播放过程中可能出现的错误进行捕获和处理的接口,例如网络连接错误、媒体解码错误等。 以上是基于HarmonyOS的视频播放器所需要的一些接口。根据具体需求,还可以根据实际场景进行适当的扩展和调整。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值