RPC (원격 프로 시저 호출)와 접촉했는데, 이는 원격 기계에서 로컬에서 프로그램을 호출 할 수있는 방법입니다. 나는 간단한 nodejs 구현을 보았는데,이 구현은 rpc : nodejs light_rpc의 원리를 배우는 데 매우 좋습니다.
사용의 예 :
코드 사본은 다음과 같습니다.
// 서버 측
var light_rpc = require ( './ index.js');
var port = 5556;
var rpc = new light_rpc ({
결합 : 함수 (a, b, 콜백) {
콜백 (A + B);
},
곱하기 : 함수 (t, cb) {
CB (T*2);
}
}). 듣기 (포트);
샘플 클라이언트 :
코드 사본은 다음과 같습니다.
//고객
rpc.connect (5556, 'localhost', function (remote, conn) {
remote.combine (1, 2, function (res) {
if (res! = 3) {
console.log ( 'error', res);
}
});
});
전체 과정에 대해 간단히 이야기 해 봅시다.
1. 서버 측은 프로그램을 시작하고, 포트를 듣고, 클라이언트가 호출 할 수있는 기능을 구현하고 (예 : 위의 예에서 결합 및 곱하기) 객체에 저장합니다.
2. 클라이언트 측은 프로그램을 시작하고 서버에 연결하며 연결이 완료된 후 설명 명령을 보냅니다. 서버가 호출 할 수있는 기능 이름을 반환해야합니다.
코드 사본은 다음과 같습니다.
Connection.on ( 'Connect', function () {
Connection.write (명령 (descrcmd));
});
3. 서버 쪽은 설명 명령을 수신하고 호출 할 수있는 함수 이름을 랩핑하여 보낼 수 있습니다 ( "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, 콜백, 연결) {
return function () {
var id = uuid.generate ();
if (typeof arguments [arguments.length-1] == 'function') {
콜백 [id] = 인수 [arguments.length-1];
}
var args = parseargumentStoArray.call (this, arguments);
var newcmd = 명령 (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. 함수가 완료된 후 결과를 직렬화하여 이전에받은 콜백드 ID와 함께 클라이언트쪽으로 다시 보내십시오.
코드 사본은 다음과 같습니다.
함수 getSendCommandBackFunction (Connection, CMDID) {
return function () {
var innerargs = parseargumentStoArray.call ({}, arguments);
var resultcommand = 명령 (resultcmd, {id : cmdid, args : innerargs});
Connection.write (resultCommand);
};
}
8. 클라이언트 측은 작동 실행 결과 및 콜백을 수신하고 CallbackId를 기반으로 콜백 함수를 가져오고 실행 결과를 실행을 위해 콜백 함수로 전달합니다.
9. 전체 프로세스가 완료되면 소스 코드를 참조하십시오 : https://github.com/romulka/nodejs--leight_rpc
몇 가지 메모 :
1. 전송 및 수신 후 링크를 분리하는 HTTP 프로토콜과 달리 클라이언트와 서버는 항상 프로세스 전체에 연결되어 있으므로 연결 해제를 사용하여 데이터 전송이 분리되어 완료되는지 여부를 결정할 수 없습니다. 데이터 수신이 완료되었는지 확인하기 위해 클라이언트와 서버가 보낸 데이터는 간단한 프로토콜을 따릅니다. 구분 기자가 /n : [패킷 길이 /n 데이터]와 같은 데이터 앞에 데이터 패킷과 분리기의 길이를 추가하십시오. 이러한 방식으로, 데이터를 수신 한 후, 데이터 패킷의 길이를 먼저 검색 한 다음, 누적 된 수신 된 데이터 패킷 이이 길이와 동일하거나 초과하는지 지속적으로 결정합니다. 그렇다면 데이터 전송이 완료되고 데이터를 구문 분석하고 추출 할 수 있습니다.
2. 가장 간단한 RPC는 매개 변수의 함수 유형을 고려하지 않는다는 것입니다. 예를 들어, 매개 변수가 객체 인 경우이 객체 아래에 함수 멤버가 있습니다. JSON이 직렬화되면 함수가 무시되고 서버 측 에서이 기능을 실행할 수 없습니다.
이 문제를 해결하려면 복잡한 처리가 필요합니다.
1. 원격 엔드로 전송 될 각 매개 변수를 깊게 가로 지르고, 함수 멤버를 추출하고,이 함수의 고유 ID를 생성하고, 로컬 객체에 넣고,이 ID 문자열로 기능 멤버를 교체하고,이 멤버가 실제로 함수임을 식별하십시오. 이런 식으로, 객체는 직렬화되어 전송 될 수 있습니다.
2. 서버가 통화를받을 때 매개 변수 객체에서 함수를 사용하려면 클라이언트가 클라이언트가 처리 한 함수라고 결정합니다. ID를 클라이언트로 다시 보내고 클라이언트 측면에서 콜백 기능 ID를 동일한 방식으로 클라이언트로 전달합니다.
3. 클라이언트 측은이 기능 ID를 수신 하고이 기능 엔티티를 찾아서 호출하여 서버 측에서 주어진 콜백 ID에 따라 서버쪽으로 다시 보냅니다.
4. 서버 측은 결과를 수신하고 콜백 함수를 찾고 계속 실행하고 완료합니다.
함수의 기록 방법은 다른 방식으로 완료 될 수 있습니다. 일반적인 아이디어는이 기능을 직렬화 가능한 것으로 바꾸어 원격 측면에서 호출 될 때 로컬로 기능을 찾을 수 있도록하는 것입니다. dnode의 구현을 참조 할 수 있습니다.