RPC(リモートプロシージャコール)と接触したばかりです。これは、リモートマシンのプログラムをローカルに呼び出すことができる方法です。単純なnodejsの実装を見ました。これはRPC:nodejs light_rpcの原則を学ぶのに非常に適しています
使用例:
コードコピーは次のとおりです。
//サーバー側
var light_rpc = require( './ index.js');
var port = 5556;
var rpc = new light_rpc({
結合:function(a、b、callback){
コールバック(a + b);
}、
乗算:function(t、cb){
CB(T*2);
}
})。聞きます(port);
サンプルクライアント:
コードコピーは次のとおりです。
//クライアント
rpc.connect(5556、 'localhost'、function(remote、conn){
remote.combine(1、2、function(res){
if(res!= 3){
console.log( 'error'、res);
}
});
});
プロセス全体について簡単に話しましょう。
1.サーバー側はプログラムを開始し、ポートに耳を傾け、クライアントに提供される関数を呼び出し(上記の例で組み合わせて掛けるなど)、オブジェクトに保存します。
2.クライアント側はプログラムを開始し、サーバーに接続し、接続が完了した後にdescrib式コマンドを送信し、呼び出して提供できる関数名をサーバーに返すように要求します。
コードコピーは次のとおりです。
connection.on( 'connect'、function(){
connection.write(command(descrcmd));
});
3.サーバー側は、describleコマンドを受信し、呼び出すことができる関数名をラップして送信します( "Combine"、 "Multiply")
4.クライアント側は、サーバーによって送信された関数名を受信し、独自のオブジェクトに登録し、各関数名のメソッドをラップするため、これらの関数がローカルに呼び出されると、実際にサーバー側にリクエストが送信されます。
コードコピーは次のとおりです。
for(cmd.dataのvar p){
remoteobj [p] = getRemoteCallFunction(P、self.callbacks、connection);
// getRemoteCallFunctionの実装を以下に示します
}
5.クライアント側は、サーバー側の関数を呼び出します。
1)callbackIDと呼ばれる渡されたコールバック関数の一意のIDを生成し、クライアントのオブジェクトに記録します。
2)次のデータをパックしてサーバー側に送信します。コール関数名、JSONシリアル化パラメーターリスト、CallBackID
コードコピーは次のとおりです。
関数getRemoteCallFunction(cmdname、callbacks、connection){
return function(){
var id = uuid.generate();
if(typeof arguments [arguments.length-1] == 'function'){
callbacks [id] = arguments [arguments.length-1];
}
var args = parseargumentstoarray.call(this、arguments);
var newcmd = command(cmdname、{id:id、args:args});
connection.write(newcmd);
}
}
6.サーバー側は上記の情報を受信し、データを解析し、パラメーターリストを脱上化し、関数名とパラメーターに従って関数を呼び出します。
コードコピーは次のとおりです。
var args = cmd.data.args;
args.push(getsendCommandBackFunction(c、cmd.data.id));
self.wrapper [cmd.command] .apply({}、args);
7。関数が完了したら、結果をシリアル化し、以前に受け取ったCallBackID IDと一緒にクライアント側に送り返します。
コードコピーは次のとおりです。
function getsendCommandBackFunction(connection、cmdid){
return function(){
var ineryargs = parseargumentstoarray.call({}、arguments);
var resultcommand = command(resultCmd、{id:cmdid、args:inergerargs});
connection.write(resultcommand);
};
}
8.クライアント側は、機能を実行している関数とCallBackIDを受信し、CallBackIDに基づいてコールバック関数を取り出し、実行結果を実行のコールバック関数に渡します。
9.プロセス全体が完了します。ソースコードを参照してください:https://github.com/romulka/nodejs-light_rpc
いくつかのメモ:
1.送信および受信後にリンクを切断するHTTPプロトコルとは異なり、クライアントとサーバーはプロセス全体で常に接続されているため、切断を使用してデータ送信を切断して完了するかどうかを判断できません。データ受信が完了したことを判断するために、クライアントとサーバーが送信したデータは単純なプロトコルに従います。データパケットの長さと、デリミッターIS /n:[パケット長 /nデータ]などのデータの前にセパレーターを追加します。このようにして、データを受信した後、データパケットの長さが最初に取得され、次に蓄積された受信されたデータパケットがこの長さに等しいか、それを超えるかを継続的に決定します。その場合、データ送信が完了し、データを解析して抽出できます。
2.最も単純なRPCは、パラメーター内の関数タイプを考慮していないことです。たとえば、パラメーターがオブジェクトである場合、このオブジェクトの下に関数メンバーがあります。 JSONがシリアル化すると、関数は無視され、この関数はサーバー側で実行できません。
この問題を解決するには、複雑な処理が必要です。
1.リモートエンドに送信される各パラメーターを深くトラバースし、関数メンバーを抽出し、この関数の一意のIDを生成し、ローカルオブジェクトに入れ、関数メンバーをこのID文字列に置き換え、このメンバーが実際に関数であることを特定します。このようにして、オブジェクトをシリアル化して送信できます。
2。サーバーが通話を受信すると、パラメーターオブジェクトで関数を使用する場合、これはクライアントがIDで処理し、このIDをクライアントに送り返し、クライアント側のコールバックを待機してクライアントにコールバック関数IDを渡すことであると判断します。
3.クライアント側はこの関数IDを受信し、この関数エンティティを見つけ、それを呼び出し、サーバー側から指定されたコールバックIDに従ってサーバー側に送り返します。
4.サーバー側が結果を受信し、コールバック関数を見つけ、実行を続け、完了します。
関数の記録方法は、他の方法で完了できます。一般的なアイデアは、関数をシリアル化可能なものに置き換えることです。そうすれば、関数はリモート側で呼び出されたときにローカルに見つけることができます。 DNodeの実装を参照できます。