26
Group System CGCII Cho sanghyun’s Game Classes II 1. Group System 2. Groups with Message 3. Transfer between Groups 4. Group with Execution 5. Sample Cases

GCGC- CGCII 서버 엔진에 적용된 기술 (8) - Group System

  • Upload
    -

  • View
    190

  • Download
    2

Embed Size (px)

Citation preview

Group SystemCGCIICho sanghyun’s Game Classes II

1. Group System2. Groups with Message3. Transfer between Groups4. Group with Execution5. Sample Cases

CGCIICho sanghyun’s Game Classes II

실행처리 Group System (1)

Group 은 Socket 들의 묶음 또 그것을 관리하는 객체

Group 에 관리 대상이 되려면 반드시 ICGGroupMemberable 을 상속받아야 한다 .

ICGGroupMemberable 을 상속받으면…

Group 에 포함될 수 있다 .

CGCIICho sanghyun’s Game Classes II

실행처리 Group System (2)

Group 은 다양한 용도로 사용할 수 있다 .

CGCIICho sanghyun’s Game Classes II

실행처리 Group System (3)

멤버 수만 카운트

리스트형 멤버 관리 (Member 제한이 거의 없다 .)

Group Interface 클래스

멤버 관리를 전혀 안 함 . (Enter/Leave 시 On~ 함수만 호출 )

배열형 멤버 관리

배열형 멤버 관리 + 전체 전송 기능•Send() : 멤버 전체에서 전송•SendExcept() : 하나 빼고 전체에게 전송

좌석식 관리 ( 입장하는 멤버에 좌석번호가 주어짐 )

좌석식 관리 + 전체 전송 기능•Send() : 멤버 전체에서 전송•SendTo() : 특정 Seat 의 멤버에게 전송•SendExcept() : 하나 빼고 전체에게 전송

CGCIICho sanghyun’s Game Classes II

실행처리 Group System (4)

EnterMember(SOCKET* p_pM) LeaveMember(SOCKET* p_pM)

virtual void OnMemberEntering (SOCKET* p_pM)virtual void OnMemberEntered (SOCKET* p_pM)

virtual void OnMemberLeaving (SOCKET* p_pM)virtual void OnMemberLeaved (SOCKET* p_pM)

CGCIICho sanghyun’s Game Classes II

Group 에 Enter 할수 있도록 ICGServerGroupMemberable<CSocket> 를 상속받는다 .

실행처리 Group System (5)

class CSocket :public CGNetSocket::CTCP<>

{private:

virtual void OnConnect();virtual void OnDisconnect();

virtual DWORD OnMessage(CGMSG& p_rMSG) { printf(“ 메시지 받았음” );}};

class CSocket :public CGNetSocket::CTCP<>

{private:

virtual void OnConnect();virtual void OnDisconnect();

virtual DWORD OnMessage(CGMSG& p_rMSG) { printf(“ 메시지 받았음” );}};

public NCGPoolable<CSocket>

1. Socket 이니까 당연히…

2. Group 의 Member 가 될수 있음 !

3. 객체가 Pool 에서 할당되도록 하기 위해

public ICGServerGroupMemberable<CSocket>,

CGPTR<CGroupTest> g_pgroupTest;

void CSocket::OnConnect(){

}

void CSocket:: OnDisconnect(){

}

CGPTR<CGroupTest> g_pgroupTest;

void CSocket::OnConnect(){

}

void CSocket:: OnDisconnect(){

}LeaveAllGroups();

5. this( 현 Socket) 을 g_pgroupTest 에 Enter 시킴 !

6. 접속 종료되면 Socket 은 모든 Group 에서 나온다 (Leave).

g_pgroupTest->EnterMember(this);

4. g_pgroupTest 라는 Group 이 있다면 !

CGCIICho sanghyun’s Game Classes II

Group 은 다음과 같이 정의한다 .

실행처리 Group System (6)

class CGroupTest :

{…

private:

…};

class CGroupTest :

{…

private:

…};

public CGServerGroup::CList<CSocket>,1. CSocket 가 Member 인 List 형 Group 을 사용한다.

virtual void OnMemberEntering (CSocket* p_pMember, CGMSG& p_rMSG){ printf(" 들어오는 중 ");} virtual voidOnMemberEndered (CSocket* p_pMember, CGMSG& p_rMSG) { printf(" 들어옴 ");}

virtual void OnMemberLeaving (CSocket* p_pMember) { printf( "나가는 중 ");}virtual void OnMemberLeaved (CSocket* p_pMember) { printf( "나감 ");}

2. 훅 함수들 재정의 !

CGCIICho sanghyun’s Game Classes II

실행처리 Groups with Messages (5)

• ICGMessageable 상속• Group 도 Message 를 받음 !

• ICGObservable 상속• Message 를 등록된 Observer 에 전달 !

RegisterObserver(p_gGroupTest)

OnMessage(CGMSG& p_rMSG)•MSG_TEST_A•MSG_TEST_B

• OnMessage 에서 Message 를 받았을 때NotifyMessage(p_rMSG) 를 호출하면 Observer 에게 Message 가 전달된다 !

• Message 는 Group 의 OnMessage 에서 처리된다

Message 를 Socket 객체가 아니라 Group 객체에서 처리하게 할수 있다 .

CGCIICho sanghyun’s Game Classes II

Group 에 Enter 할수 있도록 ICGServerGroupMemberable<CSocket> 를 상속받는다 . 또 Message 전달을 위해 NCGObserverable<CSocket> 를 상속받는다 .

실행처리 Groups with Messages (1)

class CSocket :public CGNetSocket::CTCP<>public ICGServerGroupMemberable<CSocket>,

public NCGPoolable<CSocket>{private:

virtual void OnConnect();virtual void OnDisconnect();

virtual DWORD OnMessage(CGMSG& p_rMSG);};

class CSocket :public CGNetSocket::CTCP<>public ICGServerGroupMemberable<CSocket>,

public NCGPoolable<CSocket>{private:

virtual void OnConnect();virtual void OnDisconnect();

virtual DWORD OnMessage(CGMSG& p_rMSG);};

1. message 를 전달할 Observerpublic NCGObserverable<CSocket>,

DWORD CSocket:: OnMessage(CGMSG& p_rMSG){

return 0;};

DWORD CSocket:: OnMessage(CGMSG& p_rMSG){

return 0;};

2. Message 는 Observer 에 먼저 Notify 한다 .NOTIFY_CGMESSAGE (p_rMSG);

3. return 값이 !0(true): 처리했다 , 0(false): 처리하지 못했다 .

CGCIICho sanghyun’s Game Classes II

Group 은 다음과 같이 정의한다 .

실행처리 Groups with Messages (3)

class CGroupTest :public CGServerGroup::CList<CSocket>,

{…

private:

…};

class CGroupTest :public CGServerGroup::CList<CSocket>,

{…

private:

…};

public ICGMessageable 1. ICGMessageable 을 상속받는다 !

virtual void OnMemberEntering (CSocket* p_pMember, CGMSG& p_rMSG){} // 들어오는 중이다virtual void OnMemberEndered (CSocket* p_pMember, CGMSG& p_rMSG); // 들어왔다virtual void OnMemberLeaving (CSocket* p_pMember); // 나가려한다virtual void OnMemberLeaved (CSocket* p_pMember) {} // 나갔다

virtual DWORD OnMessage(CGMSG& p_rMSG);

2. OnMessage 가 추가됨 !

DWORD CGroupTest ::OnMessage(CGMSG& p_rMSG){

Send(rMSG.Buffer);

return 1;};

DWORD CGroupTest ::OnMessage(CGMSG& p_rMSG){

Send(rMSG.Buffer);

return 1;};

CGCIICho sanghyun’s Game Classes II

실행처리 Groups with Messages (4)

void CGroupTest ::OnMemberEndered (CSocket* p_pMember, CGMSG& /*p_rMSG*/){

}

void CGroupTest ::OnMemberLeaving(CSocket* p_pMember){

}

void CGroupTest ::OnMemberEndered (CSocket* p_pMember, CGMSG& /*p_rMSG*/){

}

void CGroupTest ::OnMemberLeaving(CSocket* p_pMember){

}p_pMember->UnrgisterObserver(this);

3. this 를 Login Group 에 들어간다 !(Enter)

7. 현 Socket 은 모든 Group 에서 나온다 (Leave).

8. CGNETMSG 형으로 Casting

p_pMember->RegisterObserver(this);

9. 받은 것을 Group 전체에 전송

CGNETMSG& rMSG = (CGNETMSG&)p_rMSG;

Send(GetMemberEnterMeesage(p_pMember));

p_pMember->Send(GetRoomInfo());

Send(GetMemberLeaveMeesage(p_pMember));

4. 새로 들어온 Member 에게 방정보를 전송한다 .

5. 방의 모든 Member 에게 Member 입장 Message를 전송한다 .

6. 방의 모든 Member 에게 새로운 Member Leave Message 를 전송한다 .

CGCIICho sanghyun’s Game Classes II

실행처리 Groups with Messages (5)

2. CSocket 생성2. CSocket 생성3. CSocket::OnConnect() 호출3. CSocket::OnConnect() 호출

• GroupLogin 에 EnterMember(this).• GroupLogin 에 EnterMember(this).

4. Group::OnMemberEntered(…) 호출4. Group::OnMemberEntered(…) 호출

• Socket 의 Observer 로 등록• Socket 의 Observer 로 등록

6. CSocket::OnMessage() 호출6. CSocket::OnMessage() 호출

• GroupLogin 으로 Message 전달• GroupLogin 으로 Message 전달

7. Group::OnMessage() 호출7. Group::OnMessage() 호출

• 여기서 Message 처리• 여기서 Message 처리

5. Message 도착 !(MSG_REQUEST_LOGIN)

8. 접속 종료 !

9. CSocket::OnDisconnect() 호출9. CSocket::OnDisconnect() 호출

• LeaveAllGroup()!!• LeaveAllGroup()!!

10. Group::OnMemberLeaving(…) 호출10. Group::OnMemberLeaving(…) 호출

• Socket 의 Observer 로써 등록해제• Socket 의 Observer 로써 등록해제

1. 접속시도

CGCIICho sanghyun’s Game Classes II

실행처리 Group with Execution (1)

Message 를 Group 에서 처리할 수 있도록 하면 그러지 않아도 된다 !

Message 의 처리를 switch-case 문의 무한 나열로만 구성해야 하는가 ?

Message 를 Group 에서 처리하게 하면 도대체 무슨 장점이 ?

CGCIICho sanghyun’s Game Classes II

실행처리 Transfer between Groups (2)

Group 에 Message 처리를 사용해 해당 위치에서 처리할 Message 로 분할할수 있다 .

• MSG_REQUEST_LOGIN• MSG_EXIT

• MSG_REQUEST_CREATE• MSG_REQUEST_JOIN• MSG_EXIT

• MSG_GAME_START• MSG_GAME_PLAY• MSG_SURRENDER

• MSG_REQUEST_LOGOUT• MSG_SET_USERINFO

CGCIICho sanghyun’s Game Classes II

실행처리 Transfer between Groups (3)

• MSG_REQUEST_LOGIN• MSG_EXIT

• MSG_REQUEST_CREATE• MSG_REQUEST_JOIN• MSG_EXIT

• MSG_GAME_START• MSG_GAME_PLAY• MSG_SURRENDER

CGCIICho sanghyun’s Game Classes II

실행처리 Groups with Messages (1)

Group 이 아니더라도 Message 처리 객체를 분리하여 만들수 있다 !

ICGMessageable 만 상속받아 객체를 정의하면…

MSG_TEST_AMSG_TEST_B

Group 만이 Message 를 받아 처리할수 있나 ?

No! 어떤 객체든 ICGMessageable 만 상속받게 되면 가능 !

CGCIICho sanghyun’s Game Classes II

실행처리 Groups with Messages (2)

MSG_FIND_FRIENDMSG_REGI_FRIEND

MSG_UNREGI_FRIEND…

MSG_BUYMSG_SELL

MSG_REQ_LIST…

MSG_CHANGE_EQUIPMSG_MOVE_EQUIP

MSG_JOIN_PARTYMSG_LEAVE_PARTYMSG_PARTY_CHAT

MSG_...MSG_... MSG_...

MSG_...

여러 개 동시에도 가능하다 !

CGCIICho sanghyun’s Game Classes II

실행처리 Group with Execution (1)

서버는 Message 만 받아서 이벤트가 발생함에 따라 수동적 (Passive) 하게만 동작하지 않는다 .

특히 게임 서버는 능동적으로 처리되어야 하는 부분이 많다 .

일정 시간 마다 특정 Message 를 Client 에 전송해줘야 한다 . 일정 시간 접속이 없는 Socket 은 강제 접속 종료처리해야 한다 . 일정 시간 대기 후에도 특정 메시지가 도착하지 않으면 강제 진행한다 .

이런 경우 일반적으로 Thread 를 생성하여 Pooling 처리하는 것이 일반적이다 !

이런 경우 CGCII 에서는 Executor-Executable 이 있다 ?하지만 이것은 단발성 1 회 처리를 할 뿐이다 .

그래서 Scheduler-Schedulable 이 있다 !!!

일정 시간 마다 어떤 처리를 해줘야 하는 것들

CGCIICho sanghyun’s Game Classes II

실행처리 Group with Execution (2)

Scheduler• 일반적으로 ICGExecutable 을 Executor 에 걸어주는 역할• Priority Queue 로 최적화 .• ICGSchedulable 을 상속받은 객체를 추가할 수 있다 .

ICGSchedulable• Scheduler 와의 Interface class• 일반적으로 Schedulable 에서는 정의된 대로 ICGExecutable을 Executor 에다 거는 역할을 한다 .

ICGExecutable• Executor 에서 실행될 내용을 정의

CGCIICho sanghyun’s Game Classes II

실행처리 Group with Execution (3)

class CGroupLogin :public CGServerGroup::CList<CSocket>,virtual public ICGMessageable,

{private:

virtual void OnMemberEntering (CGMSG& p_rMSG);virtual void OnMemberEndered (CGMSG& p_rMSG);

virtual void OnMemberLeaving (CGMSG& p_rMSG);virtual void OnMemberLevedd (CGMSG& p_rMSG);

virtual DWORD OnMessage(CGMSG& p_rMSG);

public:

};

class CGroupLogin :public CGServerGroup::CList<CSocket>,virtual public ICGMessageable,

{private:

virtual void OnMemberEntering (CGMSG& p_rMSG);virtual void OnMemberEndered (CGMSG& p_rMSG);

virtual void OnMemberLeaving (CGMSG& p_rMSG);virtual void OnMemberLevedd (CGMSG& p_rMSG);

virtual DWORD OnMessage(CGMSG& p_rMSG);

public:

};

virtual publicCGSchedulable::NExecutable

2. ProcessExecute() 에 동작 내용 정의

CGSchedulable::NExecutable

virtual void ProcessExecute(…);

ICGExecutable: Executor 에 의해 실행 가능 !ICGSchedulable: Scheduler 에 등록 가능 ! (Scheduled Execution 가능 )

void Start();void Close ();

3. 시작 / 종료 함수 추가

CGCIICho sanghyun’s Game Classes II

실행처리 Group with Execution (4)

void CGroupLogin ::Start(){

SetInterval(100);

REGISTER_SCHEDULABLE(this);

}

void CGroupLogin ::Start(){

UNEGISTER_SCHEDULABLE(this);}

void CGroupLogin ::Start(){

SetInterval(100);

REGISTER_SCHEDULABLE(this);

}

void CGroupLogin ::Start(){

UNEGISTER_SCHEDULABLE(this);}

1. 100ms 마다 Executor 에 건다 .

2. Scheduler 에 추가 ! ( 이때부터 동작 )

3. Scheduler 에서 제거

void CGroupLogin ::ProcessExecute(…){

}

void CGroupLogin ::ProcessExecute(…){

}

4. 100ms 마다 실행할 내용 작성 !

CGCIICho sanghyun’s Game Classes II

실행처리 Samples (1)

DBMS

단순 접속 후 메시지 처리만 하는 간단한 처리는 이런 식으로 간단하게…( 웹서버 처리 형식 )

CGCIICho sanghyun’s Game Classes II

실행처리 Samples (1)

Redis

DBMS

MSG_CREATE_GAMEMSG_ENTER_GAME

MSG_REQ_GAMELIST…

MSG_FIND_FRIENDMSG_REGI_FRIEND

MSG_UNREGI_FRIEND…

MSG_BUYMSG_SELL

MSG_REQ_LIST…

MSG_CHANGE_EQUIPMSG_MOVE_EQUIP

MSG_TRY_LOT…

MSG_GAME_STARTMSG_GAME_PLAYMSG_EXIT_GAME

MSG_GAME_SURRENDER…

MSG_CLIENT_INFOMSG_REQUEST_LOGIN

매칭형 게임 서버는 아래와 같이 설계될 수 있다 .

CGCIICho sanghyun’s Game Classes II

실행처리 Samples (1)

MMO 게임 서버도 비교적 쉽게 설계가 가능하다 .( 물론 MMO 게임 서버의 경우 예제보다는 훨씬 더 복잡함 )

CGCIICho sanghyun’s Game Classes II

실행처리 결론

CGCII 에서 쉬운 서버의 개발 핵심은 복잡성을 덜어 줄 수 있는 구조적 문제이라고 본다 .

CGCII 은 단순한 기능 제공이 아니라 서버 설계의 컨셉과 구조를 제공해 준다 .그리고 이것이 생산성의 중요한 요소다 .

이러한 개념적 설계에 대한 지원이 서버 구조 설계를 손쉽게해 준다 .

또 Mix-In 등의 OOP 적인 설계로 다양한 확장성과 유연성을 제공해 준다 .

CGCIICho sanghyun’s Game Classes II

질문 ?예외처리

질문 [email protected]