용어집

멀티캐스트

한개의 메시지를 여러 호스트들에게 한번에 전달하는 것을 멀티캐스트라고 합니다. 메시지를 한 호스트에만 전달하는 것은 유니캐스트라고 부릅니다.

유니캐스트와 멀티캐스트

Reliable 메시징

Reliable 메시징(혹은 reliable send)는 송신측에서 수신측으로 보내는 메시지의 내용과 순서가 받는 측에서 항상 동일함을 보장합니다. 예를 들어 메시지 A,B,C,D,E를 보내면 받는 측에서도 A,B,C,D,E 순으로 받게 됩니다. 물론 A,B,C,D,E의 데이터도 깨지는 것이 없습니다.

Reliable 메시징은 이러한 신뢰성(reliablility)가 있다는 장점이 있지만 간혹 수신하는데 소요되는 시간이 Unreliable 메시징에 비해 느릴 수 있습니다.

참고: 3. ProudNet의 프로토콜 종류

Reliable Message

Reliable Message으로 주고 받아지는 메시지입니다.

Unreliable 메시징

Unreliable 메시징(혹은 unreliable send)는 송신측에서 수신측으로 보내는 메시지의 내용과 순서가 받는 측에서 항상 동일함을 보장하지는 않습니다. 이는 통신선의 길이와 상태에 따라 다릅니다. 예를 들어 메시지 A,B,C,D,E를 보내면 받는 측에서는 A,B,C,D,E를 받기도 하지만 같은 메시지를 두번 받거나(A,B,B,C,C,D,E) 메시지가 중간에 소실되거나(A,B,D) 순서가 다르게 메시지가 도착할 수 있습니다.(A,C,B,E,D) 그러나 메시지 내부의 데이터가 깨지는 일은 없습니다.

Unreliable 메시징이 이러한 단점을 갖고 있지만 Reliable 메시징보다 송달되는 시간이 대체로 빠릅니다.

참고: ProudNet의 프로토콜 종류

Unreliable Message

Unreliable 메시징으로 주고 받아지는 메시지입니다.

스레드 풀(Thread pool)

스레드 1개를 생성하고 제거하거나 제거하는 과정은 많은 처리량을 요구합니다. 또한 무언가를 실행중인 스레드가 많은 경우 운영 체제에 걸리는 부하가 상당합니다. 따라서 가능한 적은 갯수의 스레드를 유지하면서 스레드를 제거하거나 생성하는 과정을 최소화하기 위해서는 일정 갯수의 스레드로 구성된 1개의 집합을 두고, 필요할 때마다 그 집합으로부터 가져다 쓰고 더 이상 필요없으면 집합에 반환하는 과정이 필요합니다. (이를 스레드 풀링(Thread pooling)이라고 부릅니다.) 스레드 풀은 이러한 목적에 따라 등장한 개념입니다.

즉 스레드 풀은 여러 개의 스레드가 미리 만들어져 준비되어 있는 여러개의 스레드로 구성된 한 개의 집합을 지칭합니다.

스레드 풀은 공중화장실 앞에 한줄서기와 같습니다. 문이 열리는 족족 줄 맨 앞에 서있는 사람이 열린 문 안으로 들어가니까요.

스레드 풀링(Thread pooling)

스레드 풀(Thread pool)을 참고하십시오.

리스닝 포트(Listening Port)

서버가 클라이언트로부터의 접속을 받으려면 리스닝 포트라는 것이 있어야 합니다. 리스닝 포트란, 호스트 주소와 포트로 구성되어 있습니다. 호스트 주소는 111.222.111.222 또는 mycomputer.mydomain.com 형태로 구성되어 있는 인터넷 상에서의 주소입니다. 포트는 1000~65500 사이의 값입니다.

두 개 이상의 프로그램이 같은 리스닝 포트를 쓰지 않는한 얼마든지 리스닝 포트를 지정할 수 있습니다.

입구가 있어야 들어갈 수 있습니다. 리스닝 포트는 클라이언트가 진입하기 위한 입구인 셈입니다.”

PIDL컴파일러(ProudNet IDL)

추측 항법(dead reckoning)

ProudNet에서는 게임 캐릭터의 매끈한 위치 표현을 위해서 추측 항법(dead reckoning) 기법을 위한 도구를 제공하고 있습니다.

추측항법의 기본

추측 항법(dead reckoning) 은 대략적으로 다음과 같은 방식으로 작동합니다.

P = (V * T) + P0

여기까지 하면 캐릭터의 위치는 예측할 수 있지만, 계산된 위치 값을 바로 렌더하면 캐릭터의 위치가 뚝뚝 끊어지는 문제점이 발생합니다. 이 문제를 해결하기 위해 Proud.CPositionFollower를 사용할 수 있습니다.

Proud.CPositionFollower는 움직이는 타겟의 위치까지 주어진 시간 제한 안에 도착하도록 추적자(follower)를 이동시키는 역할을 합니다. 특히 Proud.CPositionFollower는 움직이는 타겟의 위치를 직선으로 추적할 수 있도록 만들어져 있습니다. 따라서 타 호스트의 캐릭터의 위치가 용수철같은 어색한 움직임을 일으키지 않습니다.

그러면, 추측 항법을 구현하는 나머지 단계를 설명하겠습니다.

추측 항법의 예. P(t=0,1,2)는 예측된 지점이고 붉은 선은 Proud.CPositionFollower 에 의해 보정된 캐릭터 위치입니다.

통상적으로, 호스트 A에서 캐릭터의 위치를 보내는 주기와 Proud.CPositionFollower에서 추적자가 타겟의 위치에 도달하는 시간 제한을 동일하게 설정하는 것이 좋습니다.

캐릭터의 위치를 보내는 주기는 상황마다 다릅니다. 다음은 권장 예입니다.

상황

보내는 데이터의 종류

보내는 주기의 평균

급격한 가속도 증가의 예

대규모전 RPG 게임(MMORPG)의 플레이어 캐릭터

위치(xyz),속도(xyz),바라보는 방향(z)

0.3

캐릭터의 이동 방향 전환, 스탠스, 도트, 버프

비행기 또는 차량

위치(xyz),속도(xyz),가속도(xyz), 바라보는 방향(xyz)

0.3

장애물 충돌, 급격한 선회

1인칭 슈팅 게임(FPS)의 플레이어 캐릭터

위치(xyz), 바라보는 방향(xyz)

0.03

캐릭터 이동 방향이 바뀌는 직후, 저격총 발사 순간

보내는 주기가 짧은 경우에는 송신량이 지나치게 커질 위험이 있습니다. 이러한 경우를 위해11. 송신량 자동 조절 기능 (Throttling)을 혼용하는 것을 권장합니다.

추측 항법(dead reckoning)을 구현한 예는 5. 3D 월드에서 캐릭터 동기화 를 참고하시기 바랍니다.

곡선형 추적자(Spline based follower)

Proud.CPositionFollower는 직선 뿐만 아니라 곡선으로 타겟을 쫓아가도록 하는 follower도 제공합니다. 이는 3차 함수 형태의 곡선형 추적자(spline based follower)입니다. 이것은 직선형 follower보다 더 매끈한 형태로 쫓아가는 모습을 보여줍니다. 하지만, 항상 매끈한 모습을 나타내는 것은 아니기 때문에, 게임 플레이에서 테스트해보면서 적당한 것을 선택하시는 것이 좋습니다.

원래 캐릭터(적색), 직선형 추적자(녹색) 및 곡선형 추적자(청색)의 모습

곡선형 추적자(Spline based follower)의 현 상태를 얻기 위해서는 아래 메서드들을 이용하면 됩니다. 나머지는 추측항법의 기본에서 설명하는 사용법과 동일합니다.

Proud.CPositionFollower.GetSplineFollowerPosition

Proud.CPositionFollower.GetSplineFollowerVelocity

각도에 대한 보정 처리

Proud.CPositionFollower는 위치에 대한 보정 역할을 합니다. 한편, Proud.CAngleFollower는 각도에 대한 보정 역할을 합니다. 이를 사용한 예시는 5. 3D 월드에서 캐릭터 동기화 를 참고하시기 바랍니다.

데이터 양자화

부동소수점 단위의 큰 값을 네트워크로 주고 받을 때 패킷량을 줄이는 트릭이 가능할 때가 있습니다. 예를 들어 캐릭터의 위치 x값은 100~200 사이에서만 결정되고 소수점 두자리 이하로의 정밀도는 무시되어도 될 정도라면 이 값은 100 * 100 = 10000 이하의 값으로 변환해서 주고받을 수 있으며 이렇게 되면 double(8바이트)를 word(2바이트)로 절약하게 됩니다.

이러한 트릭을 양자화(quantization)이라 지칭합니다.

이 클래스는 양자화 및 양자화의 반대 급부 기능을 제공합니다.

사용 예

Proud::CQuantizer q(-10000,10000,65535); // -10000~10000 사이의 값을 65535 등분의 정밀도로 양자화하는 기능
double a = 3423.38274f;
int b = q.Quantize(a);      // 양자화
double c= q.Dequantize(b);  // 양자화된 값으로부터 실제값을 복원

Fast Heap

ProudNet의 Fast heap은 Lookaside allocator보다 약간 더 느리지만 OS 환경에서의 메모리 할당/해제 속도보다는 훨씬 빠릅니다. 그리고 Lookaside allocator와 달리 다양한 크기의 메모리 블럭을 할당/해제가 가능합니다.

ProudNet의 Fast heap의 구현 클래스는 Proud.CFastHeap 입니다. Proud.CFastHeap 또한 lookaside allocator와 마찬가지로 모든 메모리 블럭이 파괴된 후에야 Proud.CFastHeap 객체를 제거할 수 있습니다.

Fast heap을 쓰는 방법은 다음과 같습니다.

자세한 것은 Proud.CFastHeap의 설명을 참고하십시오.

2.3 C++ 클래스의 기본 할당자로 지정하기도 본 모듈을 쓰는 좋은 방법 중 하나입니다.

C++ singleton

C++ 언어에서 singleton과 전역 변수의 차이가 있습니다. 전역 변수는 WinMain()이나 main()의 실행히 종료하기 직전에 파괴되지 않습니다. WinMain()이나 main()의 하위 호출 함수들에서 파괴됩니다. 또한 전역 변수들의 파괴 순서는 한 개의 C++ 파일의 컴파일 결과물에서나 보장되며 서로 다른 C++ 파일들의 컴파일 결과물간의 파괴 순서는 보장되지 않습니다.

하지만 C++ singleton 은 WinMain()이나 main()이 리턴하기 직전에 호출됩니다. 게다가 처음으로 singleton을 접근하는 순간 인스턴스의 생성자가 호출되며, 파괴되는 순서도 생성자가 호출된 역순으로 호출됩니다. 따라서 전역 변수보다 더 안전한 생성/파괴 규칙을 보장합니다.

다음은 C++ singleton 의 구현 예입니다.

class A
{
    A(){}
public:
    static A& Instance()
    {
        static A inst;
        return inst;
    }
    void Goo() {}
};



void Foo()
{
    A::Instance().Goo();
}

위 구현은 잘 알려진 singleton의 예입니다. 하지만 위 구현은 짧은 시간에 동시에 여러 스레드에서 singleton을 접근하는 경우 생성자가 2회 이상의 호출이 있을 수 있다는 위험이 있습니다. 위 문제를 해결하면서도 singleton 접근에 대한 critical section 부하가 없는 클래스 Proud.CSingleton를 사용하는 것을 권장합니다.

게임 서버의 운영체제(OS)

동시접속자수가 100 이하인 경우에는 게임 서버의 운영체제로 무엇을 사용하던지 상관없습니다. 하지만 동시접속자수가 그 이상을 넘어가는 경우 게임 서버의 운영체제는 서버 전용 운영체제를 쓰는 것이 성능상 큰 이익을 봅니다.

ProudNet이 지원하는 서버 전용 운영체제는 Windows Server, Linux Server 입니다.

Windows Server 2013 이상을 권장하며, Linux Server의 경우 CentOS 6, Ubuntu 12 이상에서 테스트되었습니다.