LOGIN • JOININ

GROUP SYSTEM

1... Group이란…
Group이란 많은 접속을 처리해야하는 서버의 구현을 편리하게 하기 위한 개념이자 객체라고 할수 있습니다.
단순히 접속 세션(소켓)만을 관리하는 컨테이너가 아니라  서버에서의 세션 객체의 상태(State) 혹은 위치의 개념에 해당하는 객체라고 할수 있습니다.

 예를 들어 채팅방 혹은 n대 n으로 플레이하는 게임 방이 있다면 그 게임방 하나를 그룹'Group'으로 구현할 수 있다.
하지만 Group은 단순히 컨테이너의 역할만이 아니다.
채팅방(그룹), 게임플레이 그룹 등 각 그룹에서 처리될 수 있는 메시지가 정의된다. 또 채팅방에서 일정시간마다 실행해야 하는 내용까지도 정의될수 있습니다.
또 각 그룹에 입장 혹은 퇴장할 때 처리되어야 하는 내용 역시 존재할 것이다.
따라서 그룹은 컨테이너 역할뿐만 아니라 각 소켓 객체들이 현재 처리해야할 메시지를 정의하고 실행되어야할 내용을 정의하는 상태(State)의 개념까지 가지고 있다고 할수 있습니다.
즉 그룹이란 단순한 스테이트도 컨테이너도 아닌 '위치'의 개념을 가진 것이라고 할 있습니다.

① Group는 서버의 구현을 편리하게 하기 위한 '위치 객체'라고 할수 있습니다.
② Group에 참가할 수 있는 객체를 ‘Member’라 정의합니다.
③ Member가 Group에 참가하는 것을 ‘Enter Member’라고 정의합니다.
④ Member가 Group에서 나가는 것을 ‘Leave Member’라고 정의합니다.

Group기능을 사용하면 채팅방이나 게임방 뿐만 아니라 MMORPG까지 손쉽게 구현이 가능합니다.
Group을 사용하기 위해서는 ‘CGServerGroupTemplates.h’를 Include해야 한다.


2... Group은 어떻게 사용되나…
Group이 어떤 역할을 하는지 이해하기 위해 어떤 식으로 구현되는지 좀더 예제를 들어 설명하겠습니다.
예를 들어 아래와 같은 간단한 채팅서버를 구현하려고 합니다.

① 서버에 접속하면 먼저 로긴을 합니다. 
② 로긴에 성공하면 대기방에 입장을 합니다.
③ 대기방에 입장하면 방 리스트가 보입니다. 또 일정시간만다 방 리스트를 업데이트 받습니다.
④ 대기방에서는 새로운 방을 방을 생성하거나 기존의 방에  참가할수 있습니다.
⑤ 방에 입장 후 채팅을 할수 있고 방에서 나갈수 있습니다.

위와 같은 간단한 채팅 서버를 그룹구조를 사용해 구현하고자 한다면....

"WaitRoom" 그룹, "Login" 그룹, "Chatting" 그룹  3종류의 그룹을 대략 아래와 같은 구성할수 있을 것입니다. 
Group_Sample1.png
OnMemberEnter는 멤버가 그룹에 입장했을 때 처리이고
OnMemberLeave는 멤버가 그룹에서 퇴장했을 때 처리이며
OnExectue는 일정시간마다 실행되어야할 내용입니다.
또 Message는 해당 그룹에서 처리가 정의된 메시지 입니다.

이렇게 3개의 그룹을 정의한 후 서버에 새로운 접속자가 생기면 일단은 'Login' 그룹에 입장을 시킵니다. 
입장한 세션(소켓)은 전송되어온 메시지를 소켓 객체에서 실행하는 것이 아니고 그 메시지를 자신이 속한 그룹에 전달해 처리하도록 합니다.

따라서 'Login'그룹에 입장한 소켓은 'Login'그룹에 정의되어 있는 로긴요청메시지 즉 'MESSAGE_REQUEST_LOGIN'만을 처리할수 있습니다.  

로긴요청이 정당해 로긴에 성공한다면 이제 세션(소켓)을 'Wait'그룹으로 옮깁니다.
즉 'Login'그룹에서 빠져나와서(Leave) 'Wait'그룹에 입장(Enter)합니다.

'Wait'그룹에 입장하게 되면 OnMemberEnter의 내용이 처리되게 됩니다.

또 'Wait'그룹에서는 당연히 'MESSAGE_REQUEST_CREATE_ROOM', 'MESSAGE_REQUEST_ENTER_ROON', 'MESSAGE_EXIT'의 메시지만 처리될 수 있습니다.

이렇게 세션(소켓은) 자신의 상태에 해당하는 그룹에 입장하고 퇴장함으로써 자신의 상태 혹은 위치에 해당하는 처리를 하게 되고 자신의 상태에 해당한 메시지만 처리할 수 있도록 할수 있습니다.


3... Group의 종류
Group은 ICGServerGroup을 상속받아 다양한 Group을 정의할 수 있다.
또 매우 자주 사용되는 형태는 상속받아 쉽게 사용할 수 있는 기반 Group들을 미리 구현해 제공해준다. 
채팅방, 로그인처리방 등과 같이 완전구현되어 일부 기능만 재정의 해서 사용할수 있는Group도 제공된다.
이 미리 제공해주는 기반  Group의 형태는 대략 다음과 같다.

① CGServerGroup::CArray<TMEMBER, …>
      배열형으로 관리하는 Group, 최대 Member 수가 정해져 있다.
      좌석 번호를 지정해 입장 해야 한다.

② CGServerGroup::CArraySender<TMEMBER, …>
      CGServerGroup::CArray<TMEMBER, …>에 전체 전송 기능을 추구한 것이다.

③ CGServerGroup::CArraySeart<TMEMBER, …>
      배열형으로 관리하지만 좌석번호 를 자동으로 배당해주는 Group이다.

④ CGServerGroup::CArraySeartSender<TMEMBER, …>
      CGServerGroup::CArraySeart<TMEMBER, …>에 전체 전송 기능을 추가한 것이다.

⑤ CGServerGroup::CList<TMEMBER, …>
      리스트형으로 Member를 관리하는 Group이다.

⑥ CGServerGroup::CListSender<TMEMBER, …>
      CGServerGroup::CList<TMEMBER, …>형에 전체 전송 기능을 추가한 것이다.

⑦ CGServerGroup::CCount<TMEMBER, …>
      Member객체를 관리하지 않는다. 총인원의 카운트만 수행한다.

⑧ CGServerGroup::CNoManage<TMEMBER, …>
      Member 객체에 대한 관리도 카운트도 수행하지 않는다. 
      단지 Enter와 Leave시 관련 함수들만 호출된다.

여기서는 List형 Group에 전체 전송 기능이 있는 ‘CGServerGroup::CListSender<T>’를 상속받아 만든다. 

Group.png


4... On~함수 재정의하기
Group에서 가장 중요한 것은 Member의 Enter와 Leave시 호출되는 함수들을 재정의하여 필요한 기능을 추가하는 것이다.
다양한 재정의 함수가 존재하지만 공통적으로 제공하는 가장 중요한 재정의 가능한 함수는 아래의 4가지다.
CGCII에서 미리 구현되어 제공되는 기본 그룹은 모두 공통적으로 아래의 4개 훅함수를 제공한다.

① CGRESULT OnMemberEntering(TMEMBER* _pMember, CGMSG& _MSG))
새로운 Member가 Enter할 때 호출되는 함수로 이 함수의 리턴 값에 따라 Enter의 허용여부를 결정할 수 있다. 함수의 리턴 값을  ‘CGRESULT_SUCCESS’아닌 다른 값을 리턴하면 해당 Member의 입장은 거부된다. 
만약 입장의 허용 여부에 대한 조건을 설정하거나 멤버의 입장 처리전 사전 처리가 필요한 경우에는 재정의할 필요가 있다..

② void OnMemberEntered(TMEMBER* _pMember, CGMSG& _MSG)
OnMemberEntering()함수가 ‘CGRESULT_SUCCESS’를 리턴해 입장이 허용 되면 이 함수가 호출된다. 
새로운 멤버가 입장할 경우 처리해야할 각종 처리를 작성한다.

③ uintptr_t OnMemberLeaving(TMEMBER* _pMember)
Member가 Leave해 나가기 직전 호출되는 함수로 일반적으로 Member가 퇴장할 때 처리해야할 내용을 이 함수를 재정의해 작성한다.

④ void OnMemberLeaved(TMEMBER* _pMember, _In_ uintptr_t _Result)
Member가 Leave하고 나간 이후 호출되는 함수로 OnMemberLeaving()함수의 리턴 값이 파라메터로 넘겨진다. 

GroupEnter.png



따라서 새로운 Member가 입장하거나 퇴장할 때 동작을 다르게 정의하고자 한다면 이 함수들을 재정의하여 작성하면 된다.


 예를 들어 채팅방을 만든다고 하면
채팅 방에 새로운 Member가 입장하면 방 내에 모든 멤버에게 새로운 Member가 들어왔음을 알려 주야 하며 새로운 멤버는 기존의 멤버 정보를 받아야 할 것이다.
이런 것들을 ‘OnMemberEntered()’ 함수를 재정의 하여 작성하면 된다.
 또 멤버가 방에서 퇴장할 시 방내에 멤버들에게 특정 멤버가 방에서 나감을 통보해 줘야 할 것이다. 이것들은 ‘OnMemberLeaving()’함수에 재정의하여 작성하면 된다.