欢迎来到三一办公! | 帮助中心 三一办公31ppt.com(应用文档模板下载平台)
三一办公
全部分类
  • 办公文档>
  • PPT模板>
  • 建筑/施工/环境>
  • 毕业设计>
  • 工程图纸>
  • 教育教学>
  • 素材源码>
  • 生活休闲>
  • 临时分类>
  • ImageVerifierCode 换一换
    首页 三一办公 > 资源分类 > PPT文档下载  

    【精品】客户端-服务器框架.ppt

    • 资源ID:2618994       资源大小:958.09KB        全文页数:105页
    • 资源格式: PPT        下载积分:8金币
    快捷下载 游客一键下载
    会员登录下载
    三方登录下载: 微信开放平台登录 QQ登录  
    下载资源需要8金币
    邮箱/手机:
    温馨提示:
    用户名和密码都是您填写的邮箱或者手机号,方便查询和重复下载(系统自动生成)
    支付方式: 支付宝    微信支付   
    验证码:   换一换

    加入VIP免费专享
     
    账号:
    密码:
    验证码:   换一换
      忘记密码?
        
    友情提示
    2、PDF文件下载后,可能会被浏览器默认打开,此种情况可以点击浏览器菜单,保存网页到桌面,就可以正常下载了。
    3、本站不支持迅雷下载,请使用电脑自带的IE浏览器,或者360浏览器、谷歌浏览器下载即可。
    4、本站资源下载后的文档和图纸-无水印,预览文档经过压缩,下载后原文更清晰。
    5、试题试卷类文档,如果标题没有明确说明有答案则都视为没有答案,请知晓。

    【精品】客户端-服务器框架.ppt

    客户端-服务器框架,第一部分,2,客户端-服务器框架,本讲讲解Symbian OS中的客户端-服务器框架模型描述客户端-服务器模式背后的理论为什么在Symbian OS 中使用它以及它是如何工作的?设计的实现类使用客户端-服务器模型的运行时性能,3,客户端-服务器模式,知道Symbian OS中客户端-服务器框架的结构和好处理解系统和暂时服务器的不同角色,为服务器应用程序的例子匹配适当的服务器类型,4,客户端-服务器模式,在客户端-服务器模式中客户端使用服务器提供的服务服务器接收来自客户端的请求消息并处理它们以同步或者异步的方式服务器典型的被用于管理对系统资源和服务的共享访问使用服务器是高效的,因为它可以为通过客户端会话提供服务以及被相互独立的线程中的客户端并发访问注意客户端-服务器框架也能被用于包括含有可写静态数据的代码,5,客户端-服务器概念示意图,资源,服务器,服务器,客户端,客户端API,调用客户端#2,调用客户端#1,调用客户端#3,6,客户端-服务器模式,服务器保护系统的完整性它能保证资源在客户端之间正确的共享因此所有的客户端能正确使用资源在Symbian OS中服务器运行在自己的进程中具有独立隔离的地址空间客户端对服务的访问是通过定义良好的接口进行的通过在独立的进程中使用服务器操作系统能够保证不好的编程或者恶意客户端不能破坏服务器管理的资源,7,客户端-服务器模式,服务器必须防止非法和失序的客户端请求它应该终结冒犯者典型的,会对客户端引发一个致命错误Symbian OS上绝大多数的系统服务是用客户端-服务器框架实现的特别的它们提供了异步的功能例如窗口服务器(用于访问UI资源,例如屏幕和键盘)串行通信服务器(用于访问串口)文件系统服务器,8,客户端-服务器模式,有多种方法用以启动和停止服务器:系统服务器(例如文件服务器)对于操作系统运行是必需的它们作为Symbian OS的一个部分被启动它们在OS运行期间都一直运行如果它们需要意外终止通常会强制手机重启,9,客户端-服务器模式,应用程序服务器只有当特定应用程序运行时才需要运行当客户端需要连接它们时启动只有服务器的单个实例运行(有第一个需要服务器的客户端启动)当最后的客户端会话关闭时服务器应该终止以节约系统资源这类服务器被称为暂时服务器,10,客户端-服务器模式,其他服务器要求每个应用程序一个实例例如POSIX 服务器有该应用程序启动并在它终止时关闭服务器多个应用程序可以使用相同的服务器实现每个应用程序拥有其私有的实例,11,Symbian OS客户端-服务器框架基础,知道Symbian OS客户端-服务器实现的基础,12,客户端-服务器框架基础,一个Symbian OS 服务器总是 运行在独立于客户端的线程中通常 但不是总是 运行在一个独立的进程中每个进程的内存是隔离的所以客户端和服务器不能访问彼此的地址空间因为这个原因所有的客户端-服务器通信通过消息传送发生的分离的线程/进程之间数据的传输由内核中转分别被称为线程间传输(ITC)或进程间传输(IPC),13,进程 vs 线程,进程,进程 A,共享相同进程空间的客户端和服务器通过ITC通信,在分离线程中的客户端和服务器通过IPC通信,内核中转的消息,内核中转的消息,14,客户端-服务器框架基础,客户端和服务器之间用以传送消息的通信通道被称为会话(session)会话由客户端初始化服务器端的代表已经有内核创建内核也可用作所有客户端-服务器通信的中间人,15,客户端-服务器框架基础,客户端向服务器发送一个请求通过一个标识了请求性质的消息对象还包含了其他额外参数对于简单的事务这就足够了但是对于复杂数据需要用线程间数据转移函数传递参数数据和返回值,16,客户端-服务器框架基础,一个典型的服务器具有客户端代码,用于将传递给服务器的请求进行格式化请求通过内核发送例如Symbian OS文件服务器的客户端(efile.exe)是一个真正的文件服务器客户方实现的客户端链接提供它的DLL(efsrv.dll)客户端方实现DLL对使用它的代码隐藏了私有的客户端-服务器通信协议,17,具体的文件服务器例子,efile.exe,进程边界,efsrv.dll,mytest.exe,链接到efsrv.lib 并调用其API方法,如RFs:Connect(),客户端方的服务器实现Implementation,文件服务器,客户端-服务器通信(内核中转的消息),18,客户端-服务器框架基础,服务器常被用于为其客户端提供异步服务因为它们运行在独立与客户端的线程中一个客户端可以提交向一个服务器提交多个请求(最多可以255个)但是只能有一个激活的同步请求,19,Symbian OS 客户端-服务器类,知道被Symbian OS客户端-服务器框架使用的类,以及每个类的角色的基本信息:RSessionBaseTIpcArgsTSecurityPolicyRMessage2CSession2CServer2CPolicyServer认识服务器在启动时必须初始化的对象理解用于防止Symbian OS中的服务器欺骗的机制,20,Symbian OS 客户端-服务器类,本节介绍被用来实现Symbian OS客户端-服务器框架的类这里讨论的类是Symbian OS v8.1b及其以后版本引入的用于安全进程见通信的类,21,Symbian OS客户端-服务器类,客户端方表示从RSessionBase 派生-主要的客户端一侧类是所有拥有其他对象句柄的类的基类那些对象通常是在内核中创建的一个RSessionBase 对象唯一的标识一个客户端-服务器会话被用于给服务发送消息,22,Symbian OS客户端-服务器类,RSessionBase 的大多数方法是受保护的,以确保用于访问服务器的客户端一侧的类不会直接暴露对服务器的访问接口相反,从RSessionBase 派生的类导出的函数会调用受保护的RSessionBase 方法这样“包装”了与服务器的通信,23,客户端-服务器类,24,Symbian OS 客户端-服务器类,例如类RFs 从RSessionBase 派生提供了对文件服务器的访问通过诸如RFs:Delete()和 RFs:GetDir()的方法允许与文件服务器通信,而不必暴露对它的直接访问,25,Symbian OS 客户端-服务器类,类RSessionBase 具有几个CreateSession()的重载函数用以开始新的客户端-服务器会话典型的,由客户端一侧实现的代码在其导出函数中调用例如Open()或 Connect(),它们并用于初始化会话,26,Symbian OS 客户端-服务器类,例如开始一个与文件服务器的会话需要调用RFs:Connect()它调用了RSessionBase:CreateSession()当成功打开时,相应的内核和服务器一侧对象也被创建,27,Symbian OS 客户端-服务器类,一个服务器具有唯一的名称它必须被传递给RSessionBase:CreateSession()以将客户端连接到正确的服务器客户端一侧的实现完成这些工作所以调用代码不需要知道服务器的名字,28,Symbian OS 客户端-服务器类,为了阻止“欺骗”服务器使用关键系统服务器的名字命名空间被分为“普通”和“保护”两个部分保护服务器命名空间被定义为所有以“!”字符开头的服务器名称只有拥有ProtServ 能力的进程能被允许注册以该字母开头的服务器对象ProtServ 能力允许服务器进程用一个被保护的名字注册我们在后面的讲义会再讨论这个问题,29,类 RSessionBase,多个RSessionBase:CreateSession()的重载函数接收一个整型参数aAsyncMessageSlots 该值指明了要保留的槽位个数槽位是为用于保存 已激活的异步请求那是客户端会话可以拥有的向服务器的请求数目可以为每个服务器保留的最大槽位数目是255,30,RSessionBase类,其他CreateSession()的重载函数不预先非配消息槽位的最大数目槽位从内核为该服务器管理的全局消息槽位池中获得,槽位池共有255个槽位在这个系统中每个服务器只有255个槽位可用,31,类RSessionBase,如果已激活请求的数目超过了系统池的槽位数目或者超过了为特定线程保留的槽位数目提交异步请求将失败并且立即返回,其错误码为KErrServerBusy,32,类 RSessionBase,CreateSession()重载函数的其他参数还包括TSecurityPolicy 对象它允许客户端代码向服务器指定标准例如服务器进程的安全ID(secure ID)或者调用进程的能力TSecurityPolicy 类将在后面更加详细的讨论安全IDs,能力以及平台安全也将在后续讲义中讨论,33,类 RSessionBase,给服务器发送请求通过调用RSessionBase:SendReceive()或者 RSessionBase:Send()RSessionBase:SendReceive()方法被重载以处理异步和同步请求异步请求方法接收一个TRequestStatus&参数同步请求则范围一个TInt类型的结果值RSessionBase:Send()方法发送消息给服务器,但是并不接收答复实践中,这个函数很少用到,34,The Send()和 SendReceive()方法,Send()和SendReceive()方法接收一个32位的参数用以标识客户端请求这典型的定义为客户端和服务器共享的枚举类型请求标识不需要是公开的传递给TIpcArgs 对象的参数数据的顺序也不是,35,The Send()和 SendReceive()方法,请求标识和参数数据是客户端一侧和服务器一侧实现的私有协议该协议对每个客户端-服务器实现都是特定的被包装在客户端一侧实现所导出的公开方法中调用代码不需要“理解”协议,36,从服务器断开,典型的,用于访问服务器的类都有终结方法通常是调用Close()因为该类通常是R类,而该方法是清除R类对象清楚的一般方法从内部看,该方法会调用 RHandleBase:Close()它发送一个断开消息给服务器并设置会话句柄为零服务器一接收到该消息,就结束会话通过销毁代表会话的服务器一侧的所有关联对象如果客户端有任何已激活的请求它们不被保证能够完成,37,从服务器断开,如果客户端激活请求后面跟着Close()调用,则Symbian OS认为其是一个客户端一侧的编程错误因此,引发一个致命错误在会话关闭后,服务器可能努力完成会话已激活的请求并这并不总是这样!所以客户端.应该保证在调用 Close()之前取消所有请求,38,从服务器断开,如果没有调用RSessionBase:Close()就终止了内核负责进行服务器一侧进行必要的清除工作如果服务器线程意外终止了所有等待的客户端请求将以错误码KErrServerTerminated完成这让客户端有机会对所有会话句柄进行清除一旦客户端或者服务器终止(即时后面又重新启动)终止前的会话都不能被再用,39,会话共享,可能会有多个用户客户端共享同一个RSessionBase 对象一个打开的客户端会话可以被共享同一个客户端进程的所有线程之间以及与其他进程的线程之间假定服务器支持会话共享的话一些服务器对连接到服务器上的线程限制会话共享如果尝试共享会话,会引发致命错误这是在Symbian OS v6.0引入可共享会话以前总是发生的事情,40,会话共享,CSession2,CServer2,RSessionBase,客服端 1,服务器,客服端 2,线程#1,线程#2(可以与线程#1是同一个进程或者在不同的进程中),RSessionBase:CreateSession()对相同的进程共享RSessionBase:ShareAuto()对不同的进程共享RSessionBase:ShareProtected(),41,会话共享,在客户端一侧如果一个会话能被共享.第一个连接到服务器的会话应当像通常那样用RSessionBase:CreateSession()创建一旦会话打开应该调用它的RSessionBase:ShareAuto()以使其对同一进程中其他线程是可共享的,42,会话共享,如果会话句柄能够被不同进程的线程使用则必须对其调用RSessionBase:ShareProtected()一个替代方法可共享会话通过调用RSessionBase:CreateSession()的重载函数创建该重载函数使用一个TIpcSessionType 参数EIpcSession_Sharable 用于进程内可共享(相同进程)EIpcSession_GlobalSharable 用于全局可共享会话(不同进程),43,类 TIpcArgs,类TIpcArgs 用来包裹要发送给服务器的参数例如一个TIpcArgs 对象构成了客户端-服务器请求的有效载荷它能够将最多四个参数包装在一起并且包含了每个参数的类型信息该对象也可以不包含任何参数用于没有关联载荷数据的请求,TInt SendReceive(TInt aFunction,const TIpcArgs,44,类 TIpcArgs,类TIpcArgs有一个缺省构造函数和四个模板化构造函数允许这类的对象用零到四个参数构造从内部看参数保存在一个简单的包含四个32位值的数组中构造函数中的参数依次的放到数组的槽位中该类也有 一组重载的 Set()函数用于显式的将参数值设置到数组的特定槽位,45,方法 Set()指明要使用的槽位和要保存的32位值它可以是TIntRHandleBaseTAny*TDes16*TDes8*TIpcArgs 类的更多内容会很快在后面介绍,类 TIpcArgs,46,类 TSecurityPolicy,类TSecurityPolicy代表了一种一般性的安全策略由客户端一侧实现代码传递给服务器拥有它的客户端将一个或多个这种对象到服务器指定客户端进程应该进行那些安全检查它指明了客户端API用户对服务器 的访问权限在用于它访问服务器之前,47,类 TSecurityPolicy,TSecurityPolicy 指定的安全策略包括:检查能力在0到7之间检查给定的安全标识(Security Identifier)其能力0-3之间检查给定的商家标识(Vendor Identifier)其能力0-3之间如果指定了多个能力它们全部要通过安全检查,48,类 RMessage2,类 RMessage2代表了服务器一层的客户端请求名字中的 2 指明这是该类的第二个版本最初的类RMessage用于Symbian OS v8.1b及其以前的版本但是后来已经本替换因为引入了安全进程间通信,49,RMessage2 与 TIpcArgs的关系,50,类 RMessage2,类RMessage2 从RMessagePtr2 派生RMessagePtr2 提供了一个由客户端发送的消息的句柄RMessage2 通过封装关联到消息的数据对它进行了扩展每个发送给服务器的客户端请求被表示成一个独立的RMessage2 对象客户端不直接使用 RMessage2,51,类 RMessage2,RMessage2 对象是TIpcArgs 和请求标识符在服务器一侧的等价对象在客户端发出请求时由内核创建例如通过调用RSessionBase:SendReceive()连接服务器或者关闭会话,52,类 RMessage2,32位的请求标识符也被称为操作码可以通过Function()提取TIpcArgs 提供的四个参数槽位可以通过调用Int0()访问以返回请求数组的第一个32位元素值Int1()返回第二个元素直到通过Int3()返回第四个函数,53,类 RMessage2,以相似的方法Ptr0()以TAny*指针的形式返回请求数组的第一个元素的内容 Ptr1()返回第二个与元素的内容以此类推,由Ptr3()返回第三个元素的内容这样,请求数据参数的结构对每个客户端请求都是预先确定的它可以从RMessage2 对象适当的槽位中提取数据,54,类 RMessage2,指针从Ptr0(),Ptr1(),Ptr2()和 Ptr3()返回的不能由服务器代码直接使用,如果它们指向运行在不同进程的客户端的地址空间的话作为替代,服务器必须使用RMessagePtr2中的ReadL()和WriteL()重载方法它们使用由内核中转的进程间通信来传输数据,55,类 RMessage2,当服务器已经服务了一个客户端请求它会调用RMessage2的RMessagePtr2:Complete()方法该方法通知客户端请求已经完成该方法包装了对客户端线程句柄函数RThread:RequestComplete()的调用传递给RequestComplete()的整型参数被写入到客户端的TRequestStatus 值客户端线程的请求信号量将被通知,56,类 CSession2,类CSession2 是一个抽象基类它代表了服务器中的一个客户端会话对于客户端一侧每个从RSessionBase派生的对象在服务器一侧有一个关联CSession2派生的对象被作为客户端连接请求的一部分创建,通过函数RSessionBase:CreateSession()该类的名称反映了它是这个类的第二个版本为Symbian OS v8.1中的安全IPC进行升级的,57,类 CSession2,从 CSession2 派生的类通过实现纯虚函数ServiceL()来处理进入的客户端请求典型的,ServiceL()检查进入的消息参数以了解客户端提交了那个请求然后通过对消息进行解包从而使用输入的参数当请求被处理后调用关联消息对象的Complete()以通知请求的客户端线程请求完成,58,类 CServer2,服务器一侧的基类是CServer2它是所有服务器必须实现的抽象基类系统确保对每个唯一命名的服务器只有一个CServer2派生的活动对象CServer2:StartL()将服务器添加到活动调度器(active scheduler)初始化第一个消息以接收请求,59,类 CServer2,CServer2 活动对象将从服务器所有的客户端接收请求当作事件从内核接收每个进入请求的通知事件处理方法RunL()执行使用 Message()检查 RMessage2 对象以确定是否CServer2 派生的对象自己能够处理请求例如 连接或者断开请求,60,类 CServer2,如果CServer2:RunL()函数不能处理请求它将请求交给服务器一侧合适的CSession2派生类的ServiceL()方法服务完每个请求之后RunL()重新提交一个“消息接收(message receive)”请求然后进一步等待客户端请求,61,活动对象协定,由于CServer2 从CActive派生活动对象的协定应该遵守特别是请求应该在服务器中得到快速而高效的处理例如一个长时运行的异步请求应该委托给服务器内的另一个活动对象这样它就可以被处理成一个增量任务这使得服务可以在后台处理长时运行请求请求时,仍能保持对进入请求的响应,62,类 CPolicyServer,CPolicyServer 实现了安全策略通过扩展通常的CServer2 类该类根据安全策略检查接收到的消息根据检查的结果采取行动正确的行为在构造时定义当接收到一个消息时消息的操作码数被用于提取关联的策略索引不同的索引值有下列不同的用法,63,CPolicyServer 策略枚举,TSpecialCase:EAlwaysPass 该消息像通常的那样被传递到会话的ServiceL()方法予以处理如果是一个连接消息创建一个新会话TSpecialCase:ENotSupported返回一个错误码 KErrNotSupported 即完成TSpecialCase:ECustomCheck调用虚函数 CustomSecurityCheckL()返回一个数值,指示是否处理该消息或者使其失败,64,The CPolicyServer Policy Enumerations,如果没有使用任何枚举值If none of the enumerations apply 策略索引被当作查找值(lookup value)用于CPolicyServer 服务构造时定义的安全策略数组关联的策略元素被用于间车正被处理消息如果消息满足策略指定的属性它将被正常处理,65,类 CPolicyServer,最后的动作是调用CPolicyServer:CheckFailedL()使得在关联的策略元素中指定的动作值该动作要么以错误码KErrPermisisonDenied完成请求对客户端线程引发致命错误调用CPolicyServer:CustomFailureActionL()以执行指定的失败动作,66,服务器一侧启动,当创建一个服务器时,需要为服务器分配一个清除栈一个活动调度器这应该在启动时完成清除栈通过调用CTrapCleanup:New()创建活动调度器按照活动对象一章所介绍的方法创建和安装,67,客户端-服务器框架,客户端-服务器模式Symbian OS 客户端-服务器框架基础Symbian OS 客户端服务器类客户端-服务器数据传输,客户端-服务器框架,第二部分,69,客户端-服务器框架,本讲介绍一个“经典的”客户端服务器例子使用客户端-服务器模型的运行时性能,70,回顾:客户端-服务器类,23,71,回顾:RMessage2 与TIpcArgs的关系,72,客户端-服务数据传输,知道客户端服务器为同步和异步请求传输数据的基本方法了解从派生自RSessionBase的客户端传送数据给Symbian OS服务器的正确代码知道如何提交同步和起步请求知道如何将基本及定制数据类转换成适当的载荷,该载荷能够以只读以及可读写请求参数的形式被传送到服务器,73,客户端-服务器数据传输,我们将要介绍的例子假定客户端和服务器运行在不同的进程中这意味着在它们之间进行数据传输需要使用进程间通信(IPC)参数数据永远不能用简单的C+指针进行传递因为服务器绝不直接访问客户端的地址空间(反之亦然)数据从客户端传递给服务器以请求消息中32位值的形式或者以指向客户端地址空间中一个描述符的指针形式服务器通过内核中转数据传输的方式访问它,74,客户端-服务器数据传输,给对此感兴趣的朋友.本例子使用大量的精力(赫克拉斯的磨难)来验证数据传输赫克拉斯是一个希腊神话任务,网站http:/有这个神话的背景介绍,75,客户端-服务器数据传输,一组枚举值用于标识客户端向服务器请求的是那个服务,enum THerculeanLabors ESlayNemeanLion,ESlayHydra,ECaptureCeryneianHind,ESlayErymanthianBoar,ECleanAugeanStables,ESlayStymphalianBirds,ECaptureCretanBull,ECaptureMaresOfDiomedes,EObtainGirdleOfHippolyta,ECaptureOxenOfGeryon,ETakeGoldenApplesOfHesperides,ECaptureCerberus,ECancelCleanAugeanStables,ECancelSlayStymphalianBirds;,76,客户端-服务器数据传输,一个 TIpcArgs 对象会被实例化并与客户端请求一起传递给相应服务器参数数据也被传递给服务器它们在TIpcArgs对象构造是传递该对象对于没有请求参数的情况缺省的,TIpcArgs 的构造函数是不带参数下面的例子描述了如何为一组不同的参数类型实现客户端-服务器请求代码,void RHerculesSession:CancelCleanAugeanStables()SendReceive(ECancelCleanAugeanStables,TIpcArgs();,77,只读基本类型,下面的代码显示了如何传递描述符和整数给服务器:,/请求传递了一个常量描述符(aDes)/和一个”只读”整数(aVal)给服务器TInt RHerculesSession:SlayNemeanLion(const TDesC8,78,自定义类型:简单类型(T-类对象),前一页幻灯片显示了如何将整型和描述符传递给服务器但是自定义的数据类型怎么办呢?RHerculesSession:SlayHydra()传递一个THydraData 类型的对象THydraData 是只包含内建类型的简单结构TVersion 是定义在e32cmn.h中的一个Symbian OS 类见下一页,struct THydraData TVersion iHydraVersion;TInt iHeadCount;,79,自定义类型:简单类型(T-类对象),TVersion 是定义在e32cmn.h中的一个Symbian OS 类一个THydraData 对象大小为64位,class TVersion public:IMPORT_C TVersion();IMPORT_C TVersion(TInt aMajor,TInt aMinor,TInt aBuild);IMPORT_C TVersionName Name()const;public:TInt8 iMajor;TInt8 iMinor;TInt16 iBuild;,80,自定义类型:简单类型(T-类对象),因为THydraData 对象的大小为64 位它用于传递给服务器显得太大了,因为请求数据数组的每个元素是32位的一个指向对象的指针必须在客户端-服务器边界进行排列(marshaled).服务器一侧代码不应当试图通过由客户端传递给服务器的C+指针直接访问客户端一侧对象这个例子中服务器代码运行在不同的进程中,因此属于不同的虚拟地址空间客户端一侧任何使用客户端一侧指针的尝试,都将引发访问冲突(一个致命错误),81,自定义类型:简单类型(T-类对象),数据传输必须通过类RMessagePtr2 的进程间通信方法来执行因此,在THydraData 对象被传递给服务器之前,它必须被“描述符化(descriptorized)”包裹指针模板类TPckg 和 TPckgC 可以用于包装平坦数据对象,如THydraData,在一个指针描述符 TPtr8 中,82,客户端-服务器数据传输,RHerculesSession 的SlayHydra()方法创建一个包裹THydraData 参数的TPckg产生的描述符的大小与它所包裹的模板化对象的大小一样(64 bits=2 bytes)TPtr8 的数据指针iPtr 指向THydraData 对象的开始处,TInt RHerculesSession:SlayHydra(THydraData,83,自定义类型:简单类型(T-类对象),如果是自定义数据长度可变吗?或者不仅仅包含平坦数据,而是拥有指向其他对象的指针?后面的代码显示了一个包含了指向另一个对象或者变长数据的指针的C类,是如何排列,以便从客户端传递到服务器的类CHerculesData拥有两个对描述符指针和一个整型数值它必须使用工具代码以将其所有成员变量放入描述符中:客户端一侧外化(descriptor client-side-externalization)以及相应的代码将其从描述符中重建出来:服务器一侧内化(server-side internalization),84,自定义类型:简单类型(T-类对象),class CHerculesData:public CBase public:static CHerculesData*NewLC(const TDesC8,创建一个代表“this”的HBufC8 将this 写入到流中 从流中初始化this清晰起见,省略了构造函数,85,自定义类型:简单类型(T-类对象),CHerculesData*CHerculesData:NewLC(const TDesC8,NewLC 为描述符打开一个读入流完成实例化析构函数,从描述符参数的内容创建一个CHerculesData 实例用于服务器一侧,CHerculesData:CHerculesData()delete iDes1;delete iDes2;,86,自定义类型:简单类型(T-类对象),HBufC8*CHerculesData:MarshalDataL()const const TInt KExpandSize=128;CBufFlat*buf=CBufFlat:NewL(KExpandSize);CleanupStack:PushL(buf);RBufWriteStream stream(*buf);CleanupClosePushL(stream);ExternalizeL(stream);CleanupStack:PopAndDestroy(,创建并返回一个含有“this”内容的堆描述符用于客户端一侧,创建一个动态平坦缓冲区以保存该对象的成员数据 data动态数组的“粒度”将 this 写入流从缓冲区创建一个堆描述符完成读入 返回(将对象拥有权传递给调用者),87,自定义类型:简单类型(T-类对象),void CHerculesData:ExternalizeL(RWriteStream,将 this 写入aStream 以进行从客户端一侧到服务器一侧的排列,将iDes1 写入流或者写入一个空描述符将iDes2 写入流或者写入一个空描述符将iVal 写入流,88,自定义类型:简单类型(T-类对象),void CHerculesData:InternalizeL(RReadStream,为了在服务器一侧重新构造CHerculesData 对象使用aStream 的内容实例化this,限制最多1024 字节读入iDes1 读入iDes2读入 iVal,89,自定义类型:简单类型(T-类对象),TInt RHerculesSession:SlayErymanthianBoar(const CHerculesData,请求传递了一个C 类对象客户端一侧,90,可读写请求参数,客户端请求提交必须区分非修改参数用以传递常量数据给服务器可修改参数用于从服务器提取数据传递了可读写整数给服务器的请求使用TPckg 来描述符化TInt&(例如 可修改引用),TInt RHerculesSession:CaptureCeryneianHind(TInt,91,异步请求,有一点是很重要的,即客户端一侧传递给异步请求的数据必须不是基于栈的因为服务器在客户端提交请求之后,服务器什么时候处理进来的请求数据是不确定的那些参数必须存在直到它们不能存在于栈中,当客户端一侧提交请求的函数返回了(因为这会销毁栈结构)这不仅仅应用于可读写参数也应用与只读参数,因为请求可能在服务器端进行排队也就是说它可能直到SendReceive()调用完成也没有被读到,92,异步请求,客户端必须也提交一个TRequestStatus 对象,用以接收请求完成的通知在本例中,TIpcArgs 参数被构造成空的,因为没有请求是不带参数的,void RHerculesSession:CleanAugeanStables(TRequestStatus,93,客户端-服务器框架的影响,理解使用客户端-服务器会话对运行速度潜在的影响,区分什么环境使用它是有用和必要的,什么环境是低效的认识什么场景使用客户端子会话(subsession)理解当发送客户端-服务器请求时上下文切换的影响,以及管理客户端和服务器之间通信的最好方法,以其获得最大限度的运行时效率,94,会话创建代价,一个客户端可以跟一个服务器有多个会话每个客户端会话也会消耗服务器和内核的资源对每个打开的客户端会话内核创建和保存一个代表它的对象服务器创建一个派生自CSession2的对象另外每个会话会带来内核、客户端以及服务器一侧线程的速度和内存的消耗,95,会话创建代价,客户端创建会话的数据应该最小化而不是按需创建和打开很多会话客户端代码应该努力共享单个会话为了效率 当需要使用多会话时客户端-服务器实现可以提供子会话类这将降低打开多个会话的开销,96,会话创建代价,为了使用子会话客户端必须打开一个与服务器的普通会话它可以用于创建子会话,子会话可以消耗更少的资源而且创建的速度也更快一个典型的客户端子会话实现从RSubSessionBase 派生和从RSessionBase派生客户端会话类似该实现类提供了简单的包装函数以隐藏子会话的细节,97,会话创建代价,使用子会话的一个很好例子就是RFile 它从RSubSessionBase 派生是一个连接到文件服务器的RFs 客户端会话的子会话一个RFile 对象表示访问单个文件的子会话,98,性能代价,当使用客户端-服务器模型时,了解其系统性能问题是非常重要的客户端和服务器之间传输数据的数量并不会引起太大的开销但是通信的频率则会引起主要的开销是由于从客户端线程到服务器线程之间传送消息所需要的线程上下文切换反之亦然如果客户端线程和服务器线程运行在不同进程中,则还需要进行进程上下文切换,99,性能代价,线程间的上下文切换保存当前运行线程的状态,用要替换线程以前的状态来覆盖它如果客户端和服务器线程在同一个进程中线程上下文切换保存线程的处理器的寄存器数据如果客户端和服务器运行在两个独立的进程中除了线程上下文切换进程上下文(对线程可访问的地址空间)必须必须保存和恢复MMU必须对每个进程重新映射内存块在一些硬件上,这意味着高速缓冲存储器(cache)必须进行清洗(flushed),100,性能代价,线程或进程间上下文切换所需要的代价的准确性质依赖于实际的硬件运行在不同进程中的线程间数据传递也有代价因为属于客户端的数据区域必须被重新映射到服务器的地址空间,101,性能提高,因为性能的原因,当在客户端和服务器之间传递数据时在单个事务中传递大量数据比进行多次传递要更可取客户端和服务器之间传输数据的数量没有上限但是节省上下文切换时间的考虑必须与存储和管理大块请求数据所消耗的内存之间进行平衡,102,性能提高,例如向或者从文件服务器频繁传输数据的组件通常不会直接使用文件系统访问方法,如RFile:Read()or RFile:Write()而是倾向于使用流存储 APIs这些API方法已经被优化以提高访问文件服务器的效率当存储数据到文件时,流APIs 将其缓存在客户端一侧然后一次性的将其传递给文件服务器(而不是每接收到一次就发送一块数据),103,性能提高,RWriteStream 使用客户端一侧缓冲区保存它要传递的数据只有昂缓冲区满时才访问文件服务器将数据写入或者流的拥有者调用了CommitL()方法RReadStream 当它创建时从源文件读取数据对缓冲区进行预填充当流拥有者希望访问文件中的数据时,流使用缓冲区获取需要的部分数据(而不是直接调用文件服务器),104,性能提高,当编写使用服务器(例如文件服务器)的代码时很值得仔细考虑一下如何使文件访问最高效例如,文件服务器提供获取文件系统中单个目录项的方法但是通常读入整个目录项然后在客户端一侧扫描它们往往更加高效.而不是跨越进程边界,多次的获取目录项一个编码良好的客户端实现户层现高层的API,这样一个事务会执行许多服务器一侧动作,105,客户端-服务器框架,客户端-服务器数据传输(例子)客户端-服务器框架的影响,

    注意事项

    本文(【精品】客户端-服务器框架.ppt)为本站会员(文库蛋蛋多)主动上传,三一办公仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对上载内容本身不做任何修改或编辑。 若此文所含内容侵犯了您的版权或隐私,请立即通知三一办公(点击联系客服),我们立即给予删除!

    温馨提示:如果因为网速或其他原因下载失败请重新下载,重复下载不扣分。




    备案号:宁ICP备20000045号-2

    经营许可证:宁B2-20210002

    宁公网安备 64010402000987号

    三一办公
    收起
    展开