作者:刘旭晖 Raymond转载请注明出处
Email:[email protected]
BLOG:http://blog.csdn.net/colorant/
主页:http://sites.google.com/site/rgbbones/
SCIM bridge端一开始的出现是为了解决C++ ABI兼容性。在Agent端使用C++,而为GTK写的Client则是基于C实现的。为了学习它的IM Protocol的Socket通讯机制,简单分析了一下Client端的代码实现。C++学得不好,Agent端就顾不上了。。。
http://os.cqu.edu.au/usr/share/doc/scim-bridge-0.4.5/doc/developer/index.html 这篇文档按题目来说是给scim-bridge的developer看的,不过想想现在GTK和QT的Client端代码都实现了,大概很少人会需要做这个工作了。(可以考虑做Clutter的Client实现 :)不过,可以由这篇文档学习了解一下Client端的工作机制。
http://os.cqu.edu.au/usr/share/doc/scim-bridge-0.4.5/doc/user/index.html scim-bridge的用户文档,基本上就是如何安装scim-bridge和查看调试信息。
Ø Im_module_init函数:注册ScimBridgeClientIMContext类。创建messenger用于Client与Agent之间的进程间通讯:如果scim-bridge的agent端没有启动,则用system命令启动agent,建立messenger与agent端的socket链接。将gtk-im-simple-context设置为缺省fallback的IMContext。
Ø Im_module_create函数:创建ScimBridgeClientIMContext对象实例。
Ø 类初始化函数:设置成员函数。
Ø 对象初始化函数:向Agent端注册自身IMContext实例,从返回的message中得到自身被注册的ID号(ID号将被用于track message的发送接收方,从而进一步将信息发送到正确的GTK Widget),并在Client本地端维护一个注册过的IMContext链表。
Ø set_client_window:通常这是GtkIMContext第一个被调用到的函数,Scim-bridge 在client端处理了改调用请求,并不将该函数调用发送到Agent端处理。
Ø 其它GtkIMContext相关函数:基本上都是做二传手的工作,将函数调用转换为message通过messenger发送给Agent端,同时将messenger接收到的message转换为对应的函数调用通知GTK或者更新IMContext状态。其中filter_keypress函数会先将key_event中各个modifie的状态解析出来,插入到message中。此外,在Developer文档中对每个函数都做了简单描述。
Messenger用于处理scim-bridge client端和agent端之间的通讯。
http://os.cqu.edu.au/usr/share/doc/scim-bridge-0.4.5/doc/developer/protocol.html 这部分文档描述了Messenger所使用的通讯协议。
Message的收发过程:
Ø Message的创建:首先根据Message的类型和参数的数量创建Message数据结构,填充类型信息,并分配其参数所需的buffer空间。每个参数默认的buffer size为10个字节。设置每个参数的具体内容,参数的结构为字符串。
Ø Message的打包:Message数据结构并不是最终在socket上传送的数据包,还需要经过打包处理,调用scim_bridge_messenger_push_message将Message的内容打包后存储在messenger的sending buffer里。此后既可释放Message结构所占据的空间。
Ø Message的发送:通过Send函数将Messenger的sending_buffer中的数据由socket发送出去。
Ø Message的接收:通过scim_bridge_messenger_receive_message从socket接收数据,当接收buffer尺寸不够时,重新分配内存。当检测到’/n’字符时,判定接收到一条完整的Message,并设置Messenger相应的标志位。
Ø Message的解包:当Messenger中接收到Message的标志位被设置后,通过调用scim_bridge_messenger_poll_message函数,将Receiving buffer中的数据再次解包出来,填充到Message结构中。
Client端Messenger相关工作流程:
Ø Messenger初始化: 在Scim-bridge Client模块初始化过程中或IMContext Focus in过程中,初始化一个全局Messenger,首先建立和Agent的socket链接。由获得的socket文件句柄,创建并初始化Messenger相关数据结构。
Ø Messenger的销毁:在Scim-bridge Client模块退出过程中或者在client与agent的socket通讯失败后,Messenger被close并销毁。
Ø Messenger socket数据的监听:在GTK Client的实现中,当Messenger创建成功后,由对应的socket文件句柄获得g_io_channel并通过g_io_add_watch添加到GTK的mainloop中,实现数据的监听。