1. 程式人生 > >淺談rpc(遠端過程呼叫)

淺談rpc(遠端過程呼叫)

資訊來源:邪惡八進位制資訊保安團隊

RPC協議2:這個協議是一個夠年頭的協議

本文介紹用於ONC RPC協議規範。此協議使用XDR語言進行描述,並文不打算描述具體的使用細節而只介紹RPC協議本身。

ONC RPC是基於RPC呼叫模型,此模型和本地過程呼叫(LPC)類似。對於LPC而言,呼叫方只需要將參加放入一些固定的地址,如暫存器,然後將程式的控制權轉交給另一個程式,最後再由那個程式返回即可。RCP與之類似,RCP在呼叫一個遠端過程後,自己進行等待狀態,傳往遠端過程的引數包括過程引數,返回引數包括執行結果。當收到包括執行結果的訊息後,本地程序從訊息中取得結果,呼叫程序重新開始執行。在伺服器一方,有一個程式在等待呼叫,當有一個呼叫到達時,伺服器程序取得程序引數,計算結果,然後返回結果。

在上面的模型中,在某一個時刻只有一個程序是活動的。ONC RCP沒有規定如何處理併發。呼叫可以同步的也可以是非同步的。伺服器可以建立一個執行緒來接收使用者請求,也可以自己來接收使用者請求。下面是RCP不同於 LPC的幾點:

1. 錯誤處理:對於遠端伺服器和網路失敗必須進行處理;
2. 全域性變數:因為遠端服務不可能訪問本地的變數,因此不能傳送全域性變數;
3. 效能:RPC通常比LPC要慢許多;
4. 認證:因為RPC通常要經過網路,因此必須進行認證。

雖然有現成的工具可以自動生成相關的伺服器和客戶方,但是協議本身仍然需要仔細設計。

RPC可由不同的傳輸協議實現,但RPC依然需要獲得傳輸層的資訊(這一過程本文不涉及)。這是因為有時候,傳輸層會限制資訊的長度,同時通訊雙方必須遵守同一個通訊協議。RPC不會試圖實現任何可靠性,應用程式應該注意相關的可靠性問題。如果RPC在TCP上執行,一切好說。TCP代替應用程式做一些工作,但如果RPC執行在UDP上,應用程式必須注意超時,重傳,多次請求檢查等工作。因為傳輸是獨立的,因此RPC必須從相關的傳輸層上獲得是否正確執行的資訊。對於UDP來講,如果應用程式沒有得到響應,它必須重新請求;重新請求後得到響應,應用程式只能推斷出伺服器至少執行了一次請求。通過對請求加上編號,可以使得伺服器不對重複的請求加以響應。因此我們可以確定在收到確定後,伺服器至多執行了一次請求。這裡需要注意的一點是:客戶的請求的ID 號只能用於和伺服器內的ID號進行相等比較,不能進行其它操作。
即使使用了TCP,在沒有得到響應時,我們也不能確定伺服器是不是一定執行了相關的操作。我們還需要使用超時機制以保證伺服器沒有失敗。RPC可以使用其它的協議,如VMTP。但本文中我們以TCP作為例子。RPC協議本身不包括繫結,這是由高層協議來完成的。RPC必須提供:

1. 被呼叫過程必須是唯一的;
2. 必須提供呼叫訊息和響應訊息的配對機制;
3. 必須提供認證機制;

除上面的要求外還必須提供對下面問題的檢測機制:

1. RPC不匹配;
2. 版本號不匹配;
3. 協議錯誤,如引數錯誤;
4. 必須提供認證錯誤的原因;
5. 提供其它錯誤資訊。

RCP呼叫有三個無符號整數域:遠端程式號,程式版本號和遠端過程號。程式號必須統一管理 ([email protected]) 。在擁有一個程式號後,我們就可以實現自己的遠端程式了。第一個實現通常以版本1來標記,這個版本號用於標記我們應該使用何種版本的程式。過程號用於標記被呼叫的程式。RCP本身可以變化,RCP訊息協議也可以變化。因此訊息本身也有RPC版本號,它通常和這裡描述的兩個版本號之一一致。返回訊息必須提供資訊以足以確定下面錯誤:

1. 遠端實現不支援版本2,返回可以支援的最高和最低版本號;
2. 遠端程式在遠端機上不可用;
3. 遠端程式不支援請求的版本號,返回支援的最高和最低版本號;
4. 請求的過程不存在;
5. 引數錯誤

認證機制要求請求訊息有兩個認證域:證書和確認。響應訊息有一個域:響應確認。RPC對這三個域統一定義如下:

enum auth_flavor {
AUTH_NONE = 0,
AUTH_SYS = 1,
AUTH_SHORT = 2
/* and more to be defined */
};

struct opaque_auth {
auth_flavor flavor;
opaque body<400>;
};

對於認證結構語義的解釋不在本協議規定之列。如果認證失敗,必須提供失敗原因。程式號成組給出,下面是一些規定:

0 - 1fffffff 由[email protected]定義
20000000 - 3fffffff 使用者定義
40000000 - 5fffffff 臨時
60000000 - 7fffffff reserved
80000000 - 9fffffff reserved
a0000000 - bfffffff reserved
c0000000 - dfffffff reserved
e0000000 - ffffffff reserved

其中第一組中要求的號碼要求所有的RPC過程必須遵守,即同一個號必須提供相同的功能。第二組主要用於除錯。第三組是由程式臨時產生的號碼。其它號碼保留,不得使用。使用者可以向伺服器傳送一組請求,稱為批處理。批處理時使用者不用等待伺服器返回,而是使用一個特定的請求獲得這一組請求的響應。批處理時通常使用TCP。而UDP多使用於廣播式RPC,對於支援廣播的伺服器,它們在成功時返回確定,在失敗時什麼也不返回(此規定可根據實現不同而不用加以遵守)。下面我們來定義RPC訊息:

enum msg_type {
CALL = 0,
REPLY = 1
};

當一個訊息接收到時,下面是呼叫遠端過程呼叫的狀態:

enum accept_stat {
SUCCESS = 0, /* RPC executed successfully */
PROG_UNAVAIL = 1, /* remote hasn't exported program */
PROG_MISMATCH = 2, /* remote can't support version # */
PROC_UNAVAIL = 3, /* program can't support procedure */
GARBAGE_ARGS = 4, /* procedure can't decode params */
SYSTEM_ERR = 5 /* errors like memory allocation failure */
};

呼叫訊息被拒絕的原因如下:

enum reject_stat {
RPC_MISMATCH = 0, /* RPC version number != 2 */
AUTH_ERROR = 1 /* remote can't authenticate caller */
};

認證失敗的原因如下:

enum auth_stat {
AUTH_OK = 0, /* success */
/*
* failed at remote end
*/
AUTH_BADCRED = 1, /* bad credential (seal broken) */
AUTH_REJECTEDCRED = 2, /* client must begin new session */
AUTH_BADVERF = 3, /* bad verifier (seal broken) */
AUTH_REJECTEDVERF = 4, /* verifier expired or replayed */
AUTH_TOOWEAK = 5, /* rejected for security reasons */
/*
* failed locally
*/
AUTH_INVALIDRESP = 6, /* bogus response verifier */
AUTH_FAILED = 7 /* reason unknown */
};

訊息體格式如下,其中XID是訊息號,請求訊息和返回訊息的訊息號必須一致。

struct rpc_msg {
unsigned int xid;
union switch (msg_type mtype) {
case CALL:
call_body cbody;
case REPLY:
reply_body rbody;
} body;
};

RPC的訊息體,版本號為2:

struct call_body {
unsigned int rpcvers; /* must be equal to two (2) */
unsigned int prog;
unsigned int vers;
unsigned int proc;
opaque_auth cred;
opaque_auth verf;
/* procedure specific parameters start here */
};

雖然cred和verf是兩個資料域,但我們通常將它們做一個處理。而響應訊息格式如下:

union reply_body switch (reply_stat stat) {
case MSG_ACCEPTED:
accepted_reply areply;
case MSG_DENIED:
rejected_reply rreply;
} reply;

如果伺服器接收這個請求,必須返回一個認證域以使自己為客戶認證:

struct accepted_reply {
opaque_auth verf;
union switch (accept_stat stat) {
case SUCCESS:
opaque results[0];
/*
* procedure-specific results start here
*/
case PROG_MISMATCH:
struct {
unsigned int low;
unsigned int high;
} mismatch_info;
default:
/*
* Void. Cases include PROG_UNAVAIL, PROC_UNAVAIL,
* GARBAGE_ARGS, and SYSTEM_ERR.
*/
void;
} reply_data;
};

伺服器可以因為版本原因或認證原因拒絕請求,下面是拒絕訊息的格式:

union rejected_reply switch (reject_stat stat) {
case RPC_MISMATCH:
struct {
unsigned int low;
unsigned int high;
} mismatch_info;
case AUTH_ERROR:
auth_stat stat;
};

認證雖然對於RPC是透明的,可是RPC必須有兩種認證必須實現。任何一種新的認證機制必須有一種獨立的認證號,這個號是統一管理的,使用者可以通過 [email protected] 獲得。其中NULL認證必須實現,我們推薦實現系統認證。NULL認證其實就是不認證,這裡推薦相關的資料域長度為0。

RPC在其它通訊協議之上,為了保證一個訊息和另一訊息分離並能夠從錯誤中進行恢復,我們規定了一個訊息片斷稱為RM,一個訊息在一個RM中。一個 RM中可以有多個記錄片斷,每個片斷除四個位元組的頭外,還有一個0到2的31次方減1的資料域。
下面我們來描述一下RPC語言,這是對XDR的一個擴充套件。下面是一個PING的例子:

program PING_PROG {
/*
* Latest and greatest version
*/
version PING_VERS_PINGBACK {
void
PINGPROC_NULL(void) = 0;
/*
* Ping the client, return the round-trip time
* (in microseconds). Returns -1 if the operation
* timed out.
*/
int
PINGPROC_PINGBACK(void) = 1;
} = 2;

/*
* Original version
*/
version PING_VERS_ORIG {
void
PINGPROC_NULL(void) = 0;
} = 1;
} = 1;

const PING_VERS = 2; /* latest version */

上程式中包括了三個小程式。通過上面的例子,我們可以看出RPC語言和XDR語言很象,不過就加了一個program-def而已。

program-def:
"program" identifier "{"
version-def
version-def *
"}" "=" constant ";"
version-def:
"version" identifier "{"
procedure-def
procedure-def *
"}" "=" constant ";"
procedure-def:
type-specifier identifier "(" type-specifier
("," type-specifier )* ")" "=" constant ";"

下面是一些基本的規定:

不使用program和version作為變數名;在一個域中版本名,過程名,版本號,過程號不能出現兩次;程式標記在一個域中是常量,只能使用未使用的常量可被指定到程式,版本和過程。最後我們來看看系統認證。如果要使用系統認證,它的標識為AUTH_SYS。證書由下面的結構表示:

struct authsys_parms {
unsigned int stamp;
string machinename<255>;
unsigned int uid;
unsigned int gid;
unsigned int gids<16>;
};

stamp是一個ID號由呼叫機產生。machinename是呼叫機的機器名,uid和gid是使用者ID和組ID,gids是包括此使用者的組的集合。一般verf指定為AUTH_NONE。這個證書只在一個特定的域內有效(此域是由機器名,使用者ID和組ID組成的)。

從伺服器接收到的Verf的認證號可以是AUTH_NONE或AUTH_SHORT。在接收到後者時,返回的是一個新的認證結構。這個新的結構可以取代原來的AUTH_SYS結構而被傳送到伺服器。這樣客戶可以傳送比較少的資料而獲得認證。伺服器保留結構和舊結構的一個對映。當然,伺服器可以隨時取消這種對映,此時客戶的請求會被拒絕。此時使用者可以必須使用原有的結構進行認證。這種認證本身並不能保證安全,真正的網路安全必須通過別的方式進行保證。

相關推薦

rpc(遠端過程呼叫)

資訊來源:邪惡八進位制資訊保安團隊 RPC協議2:這個協議是一個夠年頭的協議本文介紹用於ONC RPC協議規範。此協議使用XDR語言進行描述,並文不打算描述具體的使用細節而只介紹RPC協議本身。 ONC RPC是基於RPC呼叫模型,此模型和本地過程呼叫(LPC)類似。對於LPC而言,呼叫方只需要將參加放入一些

RabbitMQ的學習(四):RPC-遠端過程呼叫(純demo-可直接使用)

前言:在前面三篇文章中,分別對rabbitmq的搭建,並對rabbitmq常用的四種不同的交換機結合路由鍵編寫了各自的demo,可以參考: 1. RabbitMQ的學習(一):Windows下安裝及配置RabbitMQ,erlang環境變數; 2. RabbitMQ的學習(二):簡單的j

【圖文詳細 】Scala——RPC 遠端過程呼叫

1、RPC 遠端過程呼叫    1.1、RPC 概念  RPC(Remote Procedure Call)—遠端過程呼叫,它是一種通過網路從遠端計算機程式上請 求服務,而不需要了解底層網路技術的協議。RPC 協議假定某些傳輸協議的存在,如 TCP 或

用C程式碼簡要模擬實現一下RPC(遠端過程呼叫)並談談它在程式碼調測中的重要應用

        說明: 本文僅僅是一種模擬的RPC實現, 真正的RPC實現還是稍微有點複雜的。         我們來看看下面這個常見的場景: 在某系統中,我們要對某一函式進行調測, 但是, 很難很難構造出這個函式被呼叫的實際場景, 怎麼辦?         雖然很難構造

RPC遠端過程呼叫詳解

今天看了兩篇關於RPC遠端過程呼叫的,寫的很好,分享一下。 http://blog.csdn.net/mindfloating/article/details/39473807 http://blog.csdn.net/mindfloating/article/detail

RabbitMQ: RPC 遠端過程呼叫

RabbitMQ RPC 就是通過訊息佇列(Message Queue)來實現rpc的功能,就是,客戶端向服務端傳送定義好的Queue訊息,其中攜帶的訊息就應該是服務端將要呼叫的方法的引數 ,並使用Propertis告訴服務端將結果返回到指定的Queue。 1.Rabbit

RPC(遠端過程呼叫協議)簡介

RPC框架解釋 誰能用通俗的語言解釋一下什麼是 RPC 框架? - 遠端過程呼叫協議RPC(Remote Procedure Call Protocol) 首先了解什麼叫RPC,為什麼要RPC,RPC是指遠端過程呼叫,也就是說兩臺伺服器A,B,一個應用部署在A伺服器上,想

RPC遠端過程呼叫之我的理解(附帶專案希望有人交流)

最近在學習開發過程中使用到了阿里開發的dubbo框架,將專案進行分散式。 最近的學習瞭解到了一些關於RPC的原理,心血來潮就試著實現了一下自己的RPC功能。 專案主要分為三個子專案 API 專案 定義了通訊的資料模型和序列化反序列化所使用的工具以及專案測

RPC遠端過程呼叫原理及模擬RPC的Demo

什麼是 RPC由於各服務部署在不同機器,服務間的呼叫免不了網路通訊過程,服務消費方每呼叫一個服務都要寫一坨網路通訊相關的程式碼,不僅複雜而且極易出錯。如果有一種方式能讓我們像呼叫本地服務一樣呼叫遠端服務,而讓呼叫者對網路通訊這些細節透明,那麼將大大提高生產力,比如服務消費方在

RPC (遠端過程呼叫)

1、簡單元件介紹: 以Dubbo為例 RPC中可以認為有四個角色,消費者(Consumer),提供者(Provider),註冊中心(Registry),監控中心(Monitor),這個還是很好理解的,以前在同一系統的方法的呼叫者因為網路的存在,變

RPC 協議 Remote process call 遠端過程呼叫

RPC資訊協議由兩個不同結構組成:呼叫資訊和答覆資訊。 簡單的說,RPC就是從一臺機器(客戶端)上通過引數傳遞的方式呼叫另  一臺機器(伺服器)上的一個函式或方法(可以統稱為服務)並得到返回的結果。 RPC 會隱藏底層的通訊細節(不需要直接處理Socket通訊或Http通訊

RPC遠端過程呼叫)簡介

RPC(Remote Procedure Call Protocol)——遠端過程呼叫協議,它是一種通過網路從遠端計算機程式上請求服務,而不需要了解底層網路技術的協議。 之前聽過這個名詞,但是也只是大概記住了“遠端呼叫”之類的關鍵詞,而其他並沒有太多瞭解。 來到TX實習,確實如別人所說的那樣

遠端過程呼叫 RPC 及其協議

遠端過程呼叫 簡介 RPC是遠端過程呼叫(Remote Procedure Call)的縮寫形式。SAP系統RPC呼叫的原理其實很簡單,有一些類似於三層構架的C/S系統,第三方的客戶程式通過介面呼叫SAP內部的標準或自定義函式,獲得函式返回的資料進行處理後顯示或列印。

C++ RPC遠端過程呼叫

目的 最近由於摩爾定律已經不太適用,隨著大資料、計算量不斷增加,導致單機處理能力不能滿足需求,所以需要分散式計算,這就需要RPC(遠端過程呼叫),下面簡單介紹一下這個demo,來自於GitHub上的一個專案 client程式碼 #include <stri

PHP實現遠端過程呼叫RPC

一、初識RPC RPC(Remote Procedure Call)—遠端過程呼叫,它是一種通過網路從遠端計算機程式上請求服務,而不需要了解底層網路技術的協議。 二、工作原理 執行時,一次客戶機對伺服器的RPC呼叫,其內部操作大致有如下十步: 1.呼叫客戶端控制代碼;執行傳送引數

com.microsoft.sqlserver.jdbc.SQLServerException: 傳入的表格格式資料流(TDS)遠端過程呼叫(RPC)協議流不正確。此 RPC 請求中提供了過多的引數。

sqlserver在做批量插入的時候出現這個錯誤: com.microsoft.sqlserver.jdbc.SQLServerException: 傳入的表格格式資料流(TDS)遠端過程呼叫(RPC)協議流不正確。此 RPC 請求中提供了過多的引數。最多應為 2100。

Java分散式:RPC遠端過程呼叫

Java分散式:RPC(遠端過程呼叫) 引入RPC   比如我們有一個查詢的介面IDBQuery,以及其實現類DBQueryImp,如果我們執行IDBQuery查詢方法,只需要new一個DBQueryImp然後呼叫request方法即可,這就是本地函式呼叫,因為在同一個地址空間或者同一塊記憶體,通過方法棧

遠端過程呼叫(RPC)詳解

本文介紹了什麼是遠端過程呼叫(RPC),RPC 有哪些常用的方法,RPC 經歷了哪些發展階段,以及比較了各種 RPC 技術的優劣。 什麼是 RPC RPC 是遠端過程呼叫(Remote Procedure Call)的縮寫形式,Birrell 和 N

[譯]RabbitMQ教程C#版 - 遠端過程呼叫(RPC)

原文: [譯]RabbitMQ教程C#版 - 遠端過程呼叫(RPC) 先決條件 本教程假定 RabbitMQ 已經安裝,並執行在localhost標準埠(5672)。如果你使用不同的主機、埠或證書,則需要調整連線設定。 從哪裡獲得幫助 如果您在閱讀本教程時遇到困難,可以通過郵件列表 聯絡我們。