본문 바로가기

Network/Network Programming

[C++/Network] 객체 리플리케이션

 

리플리케이션은 객체의 상태를 한 호스트에서 다른 호스트로 복제 전달하는 것입니다. 직렬화를 하기 전 리플리케이션을 하기 위해 호스트는 다음의 준비 작업이 필요합니다.

 

1. 패킷

 

1. 패킷에 객체의 상태를 담은 패킷이라고 표기

 

리플리케이션이 아닌 다른 목적으로도 통신을 할 수 있기 때문에, 아래의 열거자를 사용해 패킷의 종류를 확인할 수 있게 합니다.

// PT_HELLO : 관례로 호스트가 서로 접속하면 맨 처음에 일종의 '인사' 패킷을 주고받는 것입니다.
// PT_ReplicationData : 데이터를 리플리케이션 하겠다는 것입니다.
// PT_Disconnect : 연결 해제 절차를 요청하는 것입니다.
// PT_MAX : 패킷 종류 열거형의 최댓값입니다.
enum pakcetType {
    PT_HELLO,
    PT_ReplicationData,
    PT_Disconnect,
    PT_MAX
};

 

2. 리플리케이션할 객체에 고유 식별자 부여

네트워크상으로 전송될 패킷에 번호를 매겨서 다른 호스트가 이 패킷을 받았을 때 식별자를 읽어서 참조된 객체를 조회합니다.

 

3. 리플리케이션할 객체의 클래스 식별

위의 식별자를 통해 객체를 전달받은 후 해당 객체가 어떤 클래스인지 판별합니다.

 


 

2. 상태 변경

 

게임에서 현재 월드의 상태를 패킷으로 보내야될 상황이라고 가정해보겠습니다. 게임의 규모가 작다면 전체 월드를 하나의 패킷으로 보낼 수 있을 것입니다. 그런데, 규모가 크다면 송수신할 데이터가 많기 때문에 사실상 불가능합니다.

 

그러므로, 굳이 월드 상태 전체를 패킷으로 보내지 않고 변경점을 기록한 패킷을 보낸 뒤, 수신 측이 변경 내역을 토대로 월드 상태를 갱신해주기만 하면 됩니다.

 

객체 상태는 생성, 갱신, 소멸로 구분할 수 있습니다.

enum ReplicationAction {
    RA_Create,
    RA_Update,
    RA_Destroy,
    RA_MAX
};

위의 패킷에서 ReplicationAction이 추가되었을 뿐입니다. 송신 측 수신 측 코드를 ReplicationAction에 따라서 어떻게 처리할지 지정합니다. 주의할 점은 네트워크 상에는 여러 가지 비신뢰성을 일으키는 요소들이 있으므로, 수신자가 목표 게임 객체를 찾지 못하는 경우가 있습니다. 이 경우에도 일단 해당 부분을 읽어줘야 다음 내용을 처리할 수 있기 때문에, 메모리 스트림을 읽어 들여 적절한 분량만큼 스트림을 전진시켜야 합니다.

 

이제 리플리케이션 할 때에는 변경된 부분만 리플리케이션 하면 됩니다.

enum Status_Property {
    Name = 1<<0,
    LegCount = 1<<1,
    HeadCount = 1<<2,
    Health = 1<<3,
    Max
};
 
void Write(OutputMemoryBitStream& inStream, uint32_t inProperties) {
    inStream.Write(inProperties, GetRequiredBits<MAX>::Value);
 
    if ((inProperties & Name) != 0)
        inStream.Write(mName);
    if ((inProperties & LegCount) != 0)
        inStream.Write(mLegCount);
    if ((inProperties & HeadCount) != 0)
        inStream.Write(mHeadCount);
    if ((inProperties & Health) != 0)
        inStream.Write(mHealth);
}

 


 

3. RPC(Remote Procedure Call) : 원격 프로시저 호출

 

멀티플레이 게임에서는 상태 뿐만이 아니라 어떤 기능을 수행하는 함수 자체를 수행시켜야 할 때가 있습니다. RPC는 한 호스트가 하나 이상의 다른 호스트에서 특정 프로시저가 원격 수행되도록 지시하는 행위입니다.

 

 

 

다음엔 네트워크 토폴리지에 대해 알아보겠습니다.