前言(未完。。。)
(水平有限,把我分析的和猜测的记录下来)
在学习ffmpeg 参考了雷神的代码,继承他开源的精神
VNC 核心主要包含两个部分 RFB协议, 和基于X11的键盘和鼠标的捕获,发送给服务端
改用 SDL 鼠标键盘采集数据
linux X11 XTestFakeButtonEvent 模拟鼠标输入
window mouse_event 模拟鼠标输入
实现目标
参考源码实现rfb 协议交互部分, 显示和事件捕获准备用Qt 或者SDL去写,
并加入h264的方式去更新frame (空想)
利用现有写好的ffmpeg 截图 发送 实现的实时屏幕显示 改写VNC 实现方式
基本以实现多屏监控和远程控制功能,linux 版本和window 版本
github : https://github.com/yousirui1/vnc
window 编译环境 mingw 32 + pthread lib
linux gcc
流程
XtVaAppIntitialize() //初始化窗口 appData toplevel
|
V
XtDisplay(toplevel); //显示窗口 没有设置width height 所以看不到窗口
|
V
GetArgsAndResources(); // 创建Dialog 输入 解析参数
|
V
InitialiseRFBConnection(); //tcp 报文交互 主要是认证 一问一答方式
|
V
protocol version 003.008
|
V
Securty types supproted 2 VNC 16 TightVNC
|
V
Authentication 加密方式
|
V
Share desktop flag
|
V
Server framebuffer parameters 根据 窗口大小值 色深 16bit RGB
|
V
Client set encoding 设置 支持编码格式 ZRLE ZLIB Hextitle
|
V
Client set pixel format
|
V
Client framebuffer update request
SetVisualAndCmap(); //设置色深
|
V
ToplevelInitBeforeRealization(); //设置窗口大小
|
V
DesktopInitBeforeRealization(); //创建工具栏
|
V
XtRealizeWidget(); //真正显示窗口
|
V
SetFormatAndEncodings(); //告诉服务端支持编码和解码的方式
|
V
while(1)
{
HandleRFBServerMessage(); //更新数据
}
核心
X11 捕获键盘鼠标事件发送流程
XtVaAppInitialize -> 注册fallback_resources
-> 根据注册名绑定函数地址 XtActionsRec actions[]
char *fallback_resources[] = {
"Vncviewer.title: TightVNC: %s",
"Vncviewer.translations:\
<Enter>: SelectionToVNC()\\n\
<Leave>: SelectionFromVNC()",
"*form.background: black",
"*viewport.allowHoriz: True",
"*viewport.allowVert: True",
"*viewport.useBottom: True",
"*viewport.useRight: True",
"*viewport*Scrollbar*thumb: None",
"*desktop.baseTranslations:\
<Key>F8: ShowPopup()\\n\
<ButtonPress>: SendRFBEvent()\\n\
<ButtonRelease>: SendRFBEvent()\\n\
<Motion>: SendRFBEvent()\\n\
<KeyPress>: SendRFBEvent()\\n\
<KeyRelease>: SendRFBEvent()",
"*serverDialog.dialog.label: VNC server:",
"*serverDialog.dialog.value:",
"*serverDialog.dialog.value.translations: #override\\n\
<Key>Return: ServerDialogDone()",
"*passwordDialog.dialog.label: Password:",
"*passwordDialog.dialog.value:",
"*passwordDialog.dialog.value.AsciiSink.echo: False",
"*passwordDialog.dialog.value.translations: #override\\n\
<Key>Return: PasswordDialogDone()",
NULL,
}
static XtActionsRec actions[] = {
{"SendRFBEvent", SendRFBEvent},
{"ShowPopup", ShowPopup},
{"HidePopup", HidePopup},
{"ToggleFullScreen", ToggleFullScreen},
{"SetFullScreenState", SetFullScreenState},
{"SelectionFromVNC", SelectionFromVNC},
{"SelectionToVNC", SelectionToVNC},
{"ServerDialogDone", ServerDialogDone},
{"PasswordDialogDone", PasswordDialogDone},
{"Pause", Pause},
{"RunCommand", RunCommand},
{"Quit", Quit},
};
SendRFBEvent() //发送鼠标键盘粘贴事件
bool HandleRFBServerMessage()
switch(msg.type)
{
case rfbSetColourMapEntries:
case rbfFramebufferUpdate:
case rfbEncodingCopyRect:
case rfbEncodingRRE:
case rfbEncodingCoRRE:
case rfbEncodingHextitle:
case rfbEncodingZlib:
case rfbEncodingTight:
case rfbBell:
case rfbServerCutText:
}