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 (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 적인 설계로 다양한 확장성과 유연성을 제공해 준다 .