利用rpcgen構建分佈式程序的8個步驟---學習筆記

構建分佈式程序的8個步驟(rpcgen

一、構建常規應用程序

要構建這個字典應用例子的分佈式版本,第一步要求程序員構造解決問題的常規程序。

最初這個字典應用的過程組織情況

二、將程序劃分爲兩個部分。

在考慮哪一個過程可以轉移到遠程機器上時,程序員必須考慮每一個過程所需要的設施,比如過程nextin在每一次被調用時要讀取下一輸入行,並對它進行分析,因爲它要訪問程序的標準輸入文件,所以nextin必須放在主程序中。程序員還必須考慮每個過程所要訪問的數據所處的位置。

     執行I/0或者訪問文件描述符的過程不能輕易地轉移到遠程機器中。

     執行過程的機器應當與放置過程所要訪問數據的機器是同一臺。將巨大的數據結構傳遞給遠程過程的效率很低。(可是是遠程機器,也可是客戶主機器)

     在考慮了最初的字典應用程序以及每個過程要訪問的數據之後,很明顯應當把過程insertwdeletewinitwlookupw和字典本身放在同一臺機器中。下圖表示了應用程序的劃分。

在這個劃分的基礎上,將程序分解爲本地和遠程兩個構建。

Dict1.c含有主程序和過程nextin

Dict2.c包含了來自最初的應用程序的一些過程,他們將成爲遠程程序的一部分。另外,它還包含對各個過程要共享的全局數據的聲明。

分別編譯這兩個文件,產生兩個構件的目標文件,這些構件必須連接到一起以產生可執行的程序。

三、創建rpcgen規約

程序員一旦爲某個分佈式程序選擇了一種結構,就可以準備rpc規約了,從本質上說,rpcgen規約文件包含了對遠程程序的聲明以及它所使用的數據結構。

規約文件包含:

聲明在客戶或者服務器中共享使用的常量

聲明客戶和服務器之間要共享使用的數據類型

聲明遠程程序,每個程序中所包含的過程以及它們的參數類型

Rpc使用一些數字來標識遠程程序以及在這些程序中的遠程過程。在規約文件中的程序聲明定義了諸如程序的RPC號、版本號以及分配給程序中的過程的編號。

所有這些聲明必須要用RPC編程語言給出,而不是用c語言。

文件rdict.x說明了一個rpcgen規約,它包含了對字典程序之rpc版的聲明。

按照約定,規約文件使用大寫的名字來定義過程和程序。這些名字成爲可以在C程序中使用的符號常量,大寫有助於避免衝突。

四、運行rpcgen

程序員運行rpcgen程序來檢查語法上的錯誤。Rpcgen rdict.x

Rpcgen在生成四個輸出文件時,使用了輸入文件的名字。例如,因爲輸入文件由rdict開始,所以輸出文件將被命名爲:rdict.hrdict_clnt.crdict_sve.crdict_xdr.c

① Rpcgen產生的.h文件

Rdict.h包含了在規約文件中所聲明的所有常量和數據類型的C的合法聲明。另外,rpcgen還增加了對遠程過程的定義。

Rdict.h中有外部聲明,這個被聲明的過程構成了客戶端的stub的接口部分。過程名稱不變, 只是將它們映射爲小寫,並附加上一個下劃線和程序的版本號。(例如遠程過程DELETEW,於是rdict.h含有對過程deletew_1的外部聲明。)

                           這裏是ridct.h的部分代碼。

② Rpcgen產生的xdr轉換文件

Rpcgen產生了含有對一些例程的調用的文件,這些例程執行XDR轉換。這種調用是針對遠程程序中所聲明的所有數據類型的。

③ Rpcgen產生的客戶代碼

        對於字典應用程序,rpcgen產生了文件rdict_clnt.c,這是源程序,它將成爲本程序分佈式版中客戶端的通信stub。該文件爲遠程程序中的每一個過程準備好了通信stub過程。

④ Rpcgen產生的服務器代碼

Rpc跟產生的第四個文件是rdict_svc.c,它包含服務器所需要的代碼。該文件包含服務器在開始時要執行的主程序。它包括獲得協議端口號,向端口映射器註冊RPC程序,接着便等待接收RPC調用。它將每個調用分派給合適的服務器端口stub接口,當被調用的過程響應時,服務器創建rpc應答並將它發回客戶。

該文件一旦生成,就可以被編譯成爲目標代碼的形式。

五、編寫stub接口過程

Rpcgen產生的文件並沒有構成完成的程序,它要求程序員必須編寫客戶端和服務器端的接口例程,在遠程程序中的每一個過程都必須要存在一個接口過程。

這便是在客戶端stub接口過程inserw(char *word)

在服務器端,接口例程接收來自rpcgen所產生的通信stub的調用,並將控制權傳遞給實現這個指定調用的過程。如同客戶端那樣,服務器接口例程必須把參數由rpcgen所選擇的類型轉變爲被調用過程中所使用的類型。

六、編譯和連接客戶程序

    對接口例程進行編譯,所輸出的是.o爲後綴的文件。

    程序員需要在最初的主程序中加入一點新的細節,因爲使用了rpc,程序需要有針對rpc聲明的cinclude文件,還需要包含rdict.h文件,因爲它包含了客戶和服務器都要使用的常量的定義。還需要聲明並初始化一個句柄(handle),rpc通信例程用該句柄和服務器通信。

在編譯完修改之後的主程序代碼rdict.c生成rdict.o文件之後,將客戶端的所有文件鏈接到一起,並將最終的可執行客戶程序放到文件rdict中。

cc -o rdict rdict.o rdict_clnt.o rdict_xdr.o rdict_cif.o

其中,rdict.o是我們修改之後主程序代碼編譯之後的.o文件,rdict_clnt.orpcgen產生的客戶代碼編譯生成的.o文件,rdict_cif.o是我們自己編寫的接口例程編譯之後生成的.o文件。 

七、編譯和鏈接服務器程序

 構成服務器的這些目標程序就可以用如下命令連接成可執行的文件,可執行文件放在rdictd中:

八、啓動服務器和執行客戶

     在客戶端程序運行之前,必須先開啓服務器程序,不然無法聯繫遠程程序。一定要用命令./rdictd先執行服務器程序。

注:個人理解:到目前爲止,把rpc的主要工作原理都理解了,現在做一個個人的理解分析,加深對rpc的印象。

首先,建立常規程序,然後劃分程序,在此基礎上編寫rpc規約。rpc規約是針對遠程服務器上的程序和過程制定的以(.x)爲後綴的文件。Rpc規約中包含了客戶端和服務器共享使用的常量,數據結構和遠程程序和過程的聲明,它是以數字來標識遠程程序和過程的。之後輸入命令行(rpcgen 規約文件名.x),運行rpcgen,將生產四個文件,分別爲(規約文件名.h,規約文件名_clnt.c,規約文件名_svc.c,規約文件名_xdr.c),其中.h的頭文件,是將源規約文件中的變量,數據結構和過程轉化爲c語言的形式,規約文件名_clnt.c,規約文件名_svc.c是符合rpc規範的客戶端,服務器端的源碼,對遠程程序的每一個過程都有相應的處理。之後,我們要編寫客戶端和服務器端的接口過程,這裏以常規程序中的一個函數做例子。比如insertw(char *word){}函數:在客戶端,客戶跟在常規程序中一樣還是使用void insertw(char *word){},但是這個函數已經到遠程服務器上了,無法直接調用。這時候我們就需要一個客戶端接口,能夠與rpc運行生成的客戶端程序進行通信。Rpc的客戶端程序參數是間接的,形如char **word,所以必須在我們編寫的客戶端接口對參數進行轉化,然後相應調用rpc客戶端程序中的void insertw_1(char **word){}函數。這一過程相當於對服務器發出了請求,rpc的服務器端接收到了相應的請求,調用相應函數void insertw_1_svc(char **word){},在函數中應該把參數還原成char *word,然後調用放在服務器上的void insertw(char *word){}函數,處理完成後,對客戶端的請求最返回處理。

整個過程中,程序員需要編寫的代碼主要有三塊:①rpc規約文件②客戶端接口過程③服務器端接口過程

 

發佈了25 篇原創文章 · 獲贊 8 · 訪問量 6萬+
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章