client server runtime process是什么_FreeRDP(2/5):Client

一、参考资料

“微软开发者文档中心”有详细RDP文档。如果嫌在线看麻烦,可在“Protocols”下载微软打包好的zip。

[MS-RDPBCGR]: Remote Desktop Protocol: Basic Connectivity and Graphics Remoting。要没意外,它应该是第一篇要看的RDP文档。

[MS-CSSP]: Credential Security Support Provider (CredSSP) Protocol。为了安全,RDP使用的是SSL增强版协议:CredSSP。图1指出了CredSSP何时被使用。

[MS-RDPECLIP]: Remote Desktop Protocol: Clipboard Virtual Channel Extensio。RDP以着静态虚拟通道方法扩展出更多功能,剪贴板可说是必须支持的扩展通道(通道名:cliprdr)。

二、顶层逻辑

可把整个client归为四个步骤。一是解析命令行参数,二是连接server、启动后台线程,三是不断运行、直到核心线程结束,四是退出app。

2.1 解析命令行参数

int freerdp_client_settings_parse_command_line(rdpSettings* settings, int argc, char** argv, BOOL allowUnknown);

freerdp_client_settings_parse_command_line负责从argc、argv解析命令行参数,结果存储在rdp_settings类型的变量context->settings。

/u:macbookpro15.2 /p:000000 /v:192.168.1.102

以上是三个命令行必须给出的参数。/u、/p分别指示了要登陆到server的账号和密码,/v是server的IP地址。经过解析,形成的settings是以下样子。

struct rdp_settings {
UINT32 ServerPort: 3389
char* ServerHostname: 192.168.1.102
char* Username: macbookpro15.2
char* Password: 000000
...
char* HomePath: C:Usersancientcc
char* ConfigPath: C:UsersancientccAppDataRoamingfreerdp
};

由于命令行没给出RDP端口,用默认的3389。

2.2 连接server、启动后台线程

int freerdp_client_start(rdpContext* context)

它会调用wfreerdp_client_start,后者主要执行3个任务。

  1. 调用RegisterClassEx注册Windows窗口。
  2. 创建并运行键盘输入处理线程:wf_keyboard_thread,句柄赋给keyboardThread成员变量。
  3. 创建并运行client核心处理线程:wf_client_thread,句柄赋给thread成员变量。它的运行过程基本就是client的整个生命周期。

为什么FreeRDP没把主线程作为核心线程?猜测是和3389端口用阻塞式读写有关。当使用阻塞式,并且不能保证网络质量一直很好,就会导致主线程阻塞,从而造成界面上非常不好的用户体验。

2.3 不断等待,直到核心线程wf_client_thread退出。

核心线程调用freerdp_connect连接server后,就进入while循环。一旦退出while循环,意味着线程结束。

while (1) {
  DWORD tmp = freerdp_get_event_handles(context, &handles[nCount], 64 - nCount);
  ...
  if (MsgWaitForMultipleObjects(nCount, handles, FALSE, 1000, QS_ALLINPUT) == WAIT_FAILED) {
    break;
  }
  if (!freerdp_check_event_handles(context)) {
    if (client_auto_reconnect(instance)) {
      break;
    }
  }

  quit_msg = FALSE;
  while (PeekMessage(&msg, NULL, 0, 0, PM_NOREMOVE)) {
    ...
  }
  if (quit_msg) {
    break;
  }
}

freerdp_check_event_handles是主要处理函数,内部依次调用freerdp_check_fds、freerdp_channels_check_fds。

freerdp_check_fds。检查端口(主要是3389)是有否要接收的数据,有就接收并处理。数据包括图像(Server Fast-Path Update PDU发来)、虚拟通道PUD(像server执行“粘贴”产生File Contents Request的Virtual Channel),等。可能要支持好多个虚拟通道,它在收到虚拟通道PUD、提取出通道私有数据后,不是立即执行私有动作,而是把私有数据封装到一个wStream,接着创建一个wMessage,让wMessage,wParam指向这个wStream,最后调用MessageQueue_Dispatch投递到该通道的消息队列(剪贴板是rdpdrPlugin.queue)。至于后绪私有处理,每个通道有个专门线程(剪贴板是rdpdr_virtual_channel_client_thread),它从消息队列取出消息,并处理。

虚拟通道线程不是在收到server发来的MCS Connect Response PDU with GCC后就立即创建,而是要等到连接完成后的freerdp_channels_post_connect。

不论是在wf_client_thread内处理,还是通道专门线程内处理,处理后如果须要向server发应答,像File Contents Request须要有File Contents Response,并不是立即发送,而是形成消息(wMessage),然后调用MessageQueue_Dispatch投递到消息队列channels->queue(类型:wMessageQueue)。

freerdp_channels_check_fds。从channels->queue取出消息,并逐个处理。

  • 1
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值