RemObjects 客戶端完整執行流程


RemObjects是一個強大的N層網絡框架,寫一個實現即可通過多種連接方式(http,tcp/ip,webservice...)被不同客戶端調用
這里我將通過源代碼展示一下客戶端的調用過程,因為RO封裝得實在太好,程序員根本不需要關心太多細節,只需要根據需求編寫實現即可,了解其實現原理,可增強自己的設計思想,現在請一步一步來看下這個過程
圖片
首先是客戶端調用就是這么簡單,一個TRORemoteService對象轉成服務端的一個接口,即可調用服務端的接口函數,
其實在程序啟動的時候就已經完成了大多數工作了,先是看下主窗體的文件引用
圖片 
當在界面擺上以下3個控件


 ROMessage: TROBinMessage; 
 RORemoteService: TRORemoteService;
 ROChannel: TROIndyTCPChannel;
會自動引入上圖的文件, 這里的核心文件是 uROClient
先看下其初始化代碼
圖片 
該代碼主要是創建了針對 消息類,通
道類,代理類 的管理列表對象 

_MessageClasses := TClassList.Create; 消息類列表
_ProxyClasses := TStringList.Create; 代理類列表
_TransportChannels := TStringList.Create; 通道類列表

圖片
當我們使用一種消息格式的類時, 這里以BIN格式為例,引用的uROBinMessage文件會在程序啟動之初,
將該對象處理類TROBinMessage加入消息類的列表
 圖片
通道類也一樣,這里以TROIndyTCPChannel 為例 

圖片

圖片

客戶端要調用服務端的接口INewService,需要服務端提供一個接口代理類TNewService_Proxy,
初始化時也是通過注冊函數添加到uROClient里的代理類對象,
方式和 消息類,通道類 的過程類似 
圖片 
圖片

以上部分就是程序一啟動時所做的初始化工作

=============================

回到客戶端的代碼,一句代碼是如何實現整個調用過程的呢?
圖片
首先RORemoteService是一個接口實現類對象,調用 as 操作時會使用接口查詢,看下代碼
圖片 
這里會調用 FindProxyClass 函數到_ProxyClasses 代理類列表對象里搜索我們要調用的服務端接口 INewService 的代理類,
如果找到則返回該代理類對象,因為程序啟動時 TNewService_Proxy 已經注冊到 _ProxyClassess 里,所以這里實際返回的就是
TNewService_Proxy,返回后再創建實例對象proxy := proxyclass.Create(Self); 
 構造函數的參數是 TRORemoteService 對象自身;(RORemoteService as INewService) 返回的就是代理類的對象,
那么在創建代理類對象又做了些什么呢?
圖片 TNewService_Proxy 類沒有構造函數,所以這里調用的是其父類TROProxy 的構造函數
圖片
圖片
因為 RORemoteService 的對象的 Channel,Message屬性分別為 ROChannel,ROMessage;
所以代理類對象其實就是把這兩個對象給保存起來

返回來代理類對象,接下來是調用接口函數 Sum
圖片
代理類的__GetMessage屬性獲取的就是構造函數里傳入的TRORemoteService對象的 Message 屬性
 圖片
同理獲取通道對象,所以這里的 lMessage 實際上就是窗體的  ROMessage: TROBinMessage; 對象
lTransportChannel 實際上就是窗體的 ROChannel: TROIndyTCPChannel; 對象

接下來的代碼開始對入參進行指定消息格式的打包

lMessage.InitializeRequestMessage(lTransportChannel, 'NewLibrary', __InterfaceName, 'Sum');
lMessage.Write('A', System.TypeInfo(Integer), A, []);
lMessage.Write('B', System.TypeInfo(Integer), B, []);
lMessage.Finalize;
首先是在請求數據頭里寫入要調用服務端接口及函數名稱,然后再以序列化的方式寫入入參數據 圖片
圖片
圖片
圖片
圖片
圖片

這里用到的對象序列化思想,簡單地說就是把一個對象按一定的格式保存到流對象里,這個過程可以理解為 封包
數據按消息類打包后,調用通道類進行傳輸
lTransportChannel.Dispatch(lMessage);
圖片

這里的核心函數 IntDispatch 處理了 
連接:IndyClient.Connect;
發送:IndyClient.IOHandler.Write(lStream, lStream.Size, TRUE);
接收:IndyClient.IOHandler.ReadStream(lStream);
斷開:IndyClient.Disconnect;
這里的 IndyClient 是 TIdTCPClient 類對象,
也就是 通道類TROIndyTCPChannel 底層通訊其實就是通過TIdTCPClient 實現的
 
圖片 
圖片 
服務端接收到數據后會 解包,然后調用數據頭里的接口函數,計算返回的數據再 打包  發送到客戶端,
客戶端接收到返回的數據后,再 解包,並讀取返回結果
lMessage.Read('Result', System.TypeInfo(Integer), Result, []);

以上這就是整個客戶端的調用過程


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM