Symbian中的Client/Server机制

zz2008-12-11 11:04Server和Client一般在不同的进程中运行,因此它们之间的通讯需要使用内核提供的某种IPC机制来进行通讯。Symbian提供一些封装好了的RSessionBase/CServer/CSession类供Client来建立和Server之间的连接,C /S之间通过消息(RMessage类)来进行通信,这样将内核的IPC实现细节隐藏在C++的函数调用中。 可以将Symbian中的C/S结构类似到一个基于TCP的Socket实现中。在一个典型的TCP Socket连接中,大概有如下的步骤: 1. Server启动,阻塞在Accept中等待客户请求 2. Client创建一个Socket,调用Connect尝试进行连接 3. Server从Accept返回,创建一个新的Socket和该Client进行通信 Symbian的C/S结构为: 1. Client创建一个RSessionBase,调用Connect方法连接Server 2. CServer当时阻塞在NewSessionL中,收到客户连接请求后,创建一个CSession该Client进行通信 3. 然后Client通过RSessionBase::SendReceive发送请求,Server端的CSession收到该请求并执行之 因此,RSessionBase类似于TCP Socket中的Client端的套接字,CServer就是Server端那个Listen的套接字,CSession就是Server端用来和client通信的套接字。当然它们实际上有太多的不同。 稍微具体一点的基本流程是: 首先,Server开发者一般会提供给Client一个RSessionBase的派生类,例如我们常见的RFs。在这个RSessionBase的派生类中,封装了一些函数,例如如何建立一个到Server的连接(按照惯例,该函数命名为Connect),如何将 request进行封装等。 Client于Server之间的典型通讯步骤: 1. Client调用一个RSessionBase派生类的Connect函数,例如 RMyServerSession::Connect 2. 该函数内部实现将寻找当前系统运行的Server(通过TFindServer),如果没有发现该Server运行,则; 3. 启动该Server(通过RThread::Create函数在另一个线程中启动,或者通过RProcess::Create函数在一个独立的进程中启动该Server,后面这种比较常见)。 Server被启动后,Server内部的实现大概如下: 在Server线程中,首先安装一个CActiveScheduler,然后创建一个具体的CServer对象,CServer本身继承自CActive,这样就使得Server可以被CActiveScheduler调度。然后启动该Server(调用 CServer::StartL,大概CServer的内部实现是调用基类CActive::SetActive,表明自己发出了一个请求,希望该请求完成时被调度,对于CServer,它发出的请求就是希望收到Client的连接),然后进入wait loop(调用CActiveScheduler::Start函数)。当有客户通过CreateSession发送连接请求时,Scheduler将调用CServer::NewSessionL函数。 4. Client调用RSessionBase::CreateSession函数建立一个到Server的连接(通过Server的名字)。(估计内核根据 Server名字,找到对应该名字的线程RThread,然后就可以建立一个通道,估计RSessionBase中的iHandler成员变量用来代表这个连接通道,同时估计Server端的CSession中的RThread iClient成员变量也被Server用来表示这个连接通道)。 5. 通过某种IPC机制,我们的CServer派生类的NewSesssionL函数被调用,(即Client端的CreateSession会对应到 Server端的NewSessionL函数中,当然这是由内核完成的。于是我们创建一个CSession派生类来和Client进行联系,该派生类继承来的CSession对象中包含了一个表示Client所在线程的RThread对象iClient。 6. Client通过RSessionBase的SendReceive发送一个请求并期待获得返回信息。系统内部会将之转换成一个RMessage并调用Server端CSession的一个虚拟函数。 7. Server端代表该client连接的CSession对象(在第5步时被创建)的ServiceL(const RMessage& aMessage)虚拟函数被调用,其中的aMessage对象包含了Client的请求信息。 8. Server根据该aMessage的内容,调用合适的处理函数。 9. Server调用Message().Complete()通知Client该命令处理完毕。 (任何时候都可以调用Message()来获得当前Session中的消息)。内部实现可能是给Client所在的Thread中的信号量加一(CSession中有个成员变量RThread iClient,而RThread中有一个函数可以用来给于该线程关联的信号量加一)。 大致就是如此。 一个简单的C/S端的对应关系如下: Client Server RSessionBase::Connect <---> Launch server.exe RSessionBase::CreateSession <---> CServer::NewSessionL RSessionBase::SendReceive <---> CSession::ServiceL 红色标注是已经过时不用的类或是有新类代替了。

你可能感兴趣的:(thread,tcp,server,socket,Symbian,通讯)