[게임 서버] 6.6 원격 메서드 호출
카테고리: GameServer
태그: GameServer
📦 6. 게임 네트워크 엔진 프라우드넷
👉🏻 6. 원격 메서드 호출
🔄 RMI란?
기존 방식 (6.4):
- 이벤트 함수를 통해 바이너리 데이터를 주고받았다
RMI 방식:
- RMI(원격 메소드 호출): 상대방 컴퓨터 내 프로그램의 특정 함수를 멀리서 실행
- 프라우드넷의 RMI를 사용하면 더 편리하다
📤 송신 측 코드 (Proxy)
class SenderCode {
// 자동 생성 코드
Knight_Move(SendTo, position, motion) {
Message msg;
msg.Write(ID_Knight_Move);
msg.Write(position);
msg.Write(motion);
Send(SendTo, msg);
}
}
특징:
- 함수 호출을 대신 해준다는 의미로 proxy라고 한다
📥 수신 측 코드 (Stub)
class ReceiveCode {
ProcessReceivedMessage(Message msg) {
ID = msg.Read();
switch(ID) {
case ID_Knight_Move:
position = msg.Read();
motion = msg.Read();
Knight_Move(position, motion);
break;
...
}
}
Knight_Move(position, motion) {
// 코드 작성
}
}
특징:
- 수신하는 측에서는 메시지를 받고 함수를 호출해준다
- 함수 호출해주는 기반이라는 의미로 stub이라고 한다
✨ 장점
- 송수신 처리 코드를 일일이 구현할 필요가 없다
- 송수신 메시지의 형태가 변경되어도, 송수신 코드를 수정하다 실수할 위험이 없다
🧮 계산기 구현 예시
1️⃣ RMI 함수 선언
PIDL 확장자 파일에서 선언:
global CalcC2S 1000 {
RequestAdd([in] int a, [in] int b);
}
global CalcS2C 2000 {
ResponseAdd([in] int sum);
}
구문 설명:
global <네임스페이스 이름> <메시지 ID>
네임스페이스 이름:
- 송수신 코드는 Proxy와 Stub이라는 이름의 클래스로 만들어지며, 이들은 네임스페이스 안에 들어간다
- 예:
CalcS2C::Proxy
메시지 ID:
- RMI 함수를 지칭하며, 정수 값이다
- 1000, 2000은 RMI ID의 시작 값이며, 선언하는 각각의 RMI 함수는 1큰 수를 가진다
- RMI ID를 수동 설정하는 방법은 나중에 설명한다
2️⃣ PIDL 파일 컴파일
// --- 클라이언트 ---
// 송신
CalcC2S::Proxy
// 수신
CalcS2C::Stub
CalcS2C::StubFunctional
// --- 서버 ---
// 송신
CalcS2C::Proxy
// 수신
CalcC2S::Stub
CalcS2C::StubFunctional
- PIDL 파일을 컴파일했을 때, 컴파일러가 생성하는 클래스이다
3️⃣ 클래스 사용
Stub 사용:
// CalcC2S::Stub을 사용하는 경우
class MyStub : public CalcC2S::Stub {
RequestAdd(from, rmiContext, a, b) {
// 여기에 코드 입력
}
}
myStub = new MyStub
StubFunctional 사용:
// CalcC2S::StubFunctional을 사용하는 경우
myStub = new CalcC2S:StubFunctional();
myStub.RequestAdd = [](from, rmiContext, a, b) {
// 여기에 코드 입력
}
- StubFunctional의 경우는 함수나 람다식을 넣으면 된다
4️⃣ 송신 코드(proxy)/수신 코드(stub) 부착
// 서버 측
CalcS2C::Proxy CalcS2CProxy;
s->AttachProxy(&CalcS2CProxy);
CalcC2S::StubFunctional CalcC2SStub;
s->AttachStub(&CalcC2SStub);
// 클라이언트 측
CalcC2S::Proxy CalcC2SProxy;
c->AttachProxy(&CalcC2SProxy);
CalcS2C::StubFunctional CalcS2CStub;
c->AttachStub(&CalcS2CStub);
서버:
CalcS2C.Proxy,CalcC2S.Stub필요- NetServer에 부착
클라이언트:
CalcC2S.Proxy,CalcS2C.Stub필요- NetClient에 부착
5️⃣ RMI 호출 및 호출 받기
// 서버 측
CalcS2CStub.RequestAdd_Function =
[]PARAM_CalcC2SStub_RequestAdd // 1
{
int sum = a + b;
// 2
CalcS2CProxy.ResponseAdd(remote, RmiContext::ReliableSend, sum);
};
};
// 클라이언트 측
// 3
CalcC2SProxy.RequestAdd(HostID_Server, RmiContext::ReliableSend, 3, 4);
// 4
CalcS2C.ResponseAdd_Function =
[]PARAM_CalcS2CStub_ResponseAdd
{
print(sum);
}
};
서버:
- 1번: 클라이언트가 원격 호출한
RequestAdd()함수를 람다식으로 넣어준다PARAM_으로 시작하는 매크로는 람다식의 매개변수를 미리 정의해놓은 매크로다- 매크로는 송신자의 HostID, RmiContext를 처리한다
- 2번: 처리 결과를 클라이언트의 원격 함수를 호출하여 전송한다
- remote는 수신할 때 받았던 송신자의 식별자(HostID)이다
클라이언트:
- 3번: 서버의
RequestAdd함수를 원격 호출한다- 수신자의 HostID, RmiContext, 정의한 RMI 함수의 매개변수들을 넣어준다
- 4번: 서버가 원격 호출한
ResponseAdd()함수를 람다식으로 넣어준다PARAM_으로 시작하는 매크로는 람다식의 매개변수를 미리 정의해놓은 매크로다- 매크로는 송신자의 HostID, RmiContext를 처리한다
🧐 정리
| 구성 요소 | 역할 | 위치 |
|---|---|---|
| Proxy | 원격 함수 호출 (송신) | 호출하는 쪽 |
| Stub | 원격 함수 수신 및 실행 | 호출받는 쪽 |
| PIDL | RMI 함수 정의 | 컴파일 전 |
핵심 개념:
- Proxy로 원격 함수 호출
- Stub으로 원격 호출 수신
- PIDL로 함수 선언, 자동 코드 생성
- 타입 안전성과 편의성 확보
댓글남기기