LOGIN • JOININ

SIMPLE GROUP

[Tutorials/[Server] 1. Group classes/Sever/Tutorial_GroupServer01_SimpleGroup]


1... 그룹 정의하기
예제에서는 Group클래스를 아래와 같이 정의했습니다. 
class CGroup : 
	public CGServerGroup::CListSender<CSocket>	// 1) List형 Group을 만든다.
{
protected:
	// 2) Group에 새로운 멤버가 입장했을 때 호출되는 함수.
	virtual	void	OnMemberEntered(CSocket* /*_pMember*/, CGMSG& /*_MSG*/) override	
	{
		printf("Member Entered\n");
	}

	// @) Group에서 멤버가 나갈 때 호출되는 함수.
	virtual	uintptr_t OnMemberLeaving(CSocket* /*_pMember*/) override
	{
		printf("Member Leaved\n");
			return	0;
	}
};

1) 먼저 List형에 전체 전송 기능을 가진  Group으로 정의하기 위해 ‘CGServerGroup::CListSender<TMEMEBER>’를 상속 받았습니다.
2) 새로운 Member가 입장할 시 “Member Entered”를 출력하기 위해 ‘OnMemberEntered()’함수를 재정의 했습니다.
3) Member가 퇴장할 때 “Member Leaved”를 출력하기 위해 ‘OnMemberLeaving()’함수를 재정의 했습니다.


2... 그룹의 멤버 되기 (ICGServerGroupable)
 Group에 모든 객체가 다 Enter할수 있는 것은 아닙니다. ICGServerGroupable<T>를 상속받은 객체만이 Group<T>에 입장 가능합니다.
class CSocket :
	public	CGNet::Socket::CTCP<>,
public	ICGServerGroupable<CSocket> // 1) 이것을 상속받아야 Group에 Enter할수 있다.
{
	...
};

1) ICGServerGroupable<CSocket>을 상속받아야 Group<T> 서버에 Enter가능합니다.


3... Group에 입장과 퇴장하기
새로운 클라이언트가 접속을 하면 바로 g_pgroupRoom 그룹 객체에 Enter하도록 하고 접속이 종료되면 그룹에서 Leave하기 위해  CSocket 클래스를 아래와 같이 작성했습니다.
CGPTR<CGroup>	g_pgroupRoom;

void CSocket::OnConnect()
{
	g_pgroupRoom->EnterMember(this);
}

void CSocket::OnDisconnect(uint32_t /*p_Reason*/)
{
	LeaveGroup();
}

1) 새로운 접속이 되면 OnConnect()함수가 호출된대 이때 g_pgrouopRoom에 EnterMember()를 호출해 접속된 Socket을 입장시킵니다.
2) 접속된 Socket이 접속 종료되면 그룹에서 퇴장하기 위해 OnDisconnect()함수에서 LeaveGroup()함수를 호출했습니다.


4... Group에 메시지 전송하기
메시지를 받으면 g_pgroupRoom 그룹에 모든 멤버들에게 메시지를 전송하기 위해  g_pgroupRoom의 Send()함수를 호출했습니다.
int CSocket::OnMessage(CGMSG& _MSG)
{
	if(_MSG.message==CGNETMESSAGE)
	{
		g_pgroupRoom->Send(((CGNETMSG&)_MSG).Buffer);
	}
	return	0;
}


5... Group 객체의 생성
이렇게 모든 클래스의 정의가 끝났다면 객체들을 생성해 동작시키게 하면 될 것입니다.
int _tmain(int /*argc*/, _TCHAR* /*argv*/[])
{
	// 1) Group 객체를 생성한다.
	g_pgroupRoom	 = NEW<CGroup>();

	// 2) Acceptor 객체를 생성한다.
	auto	pacceptor	 = NEW<CGNet::CAcceptor<CSocket>>();

	// 3) 20000번 포트에 Listen을 시작한다.
	pacceptor->Start(20000);

	// 4) ESC키를 누를 때까지 대기한다.
	while(_getch()!=27);

	// 5) Acceptor를 닫는다.
	pacceptor->Close();

	return 0;
}

1) 일단 앞에서 정의한 CGroup 객체를 생성해 g_pgroupRoom에 저장합니다.
2) Acceptor 객체를 생성합니다.
3) Acceptor 객체를 20000번 포트에 Listen 합니다.
4) ESC를 누를 때까지 대기합니다.
5) ESC를 눌렀다면 Acceptor를 닫고 종료합니다.


[TutorialSimpleGroup.cpp]
#include "stdafx.h"
#include "CGServerGroupTemplates.h"


class CSocket :
	public	CGNet::Socket::CTCP<>,
	public	ICGServerGroupable<CSocket>	// (@) Groupable을 상속받으면 Group에 Enter할수 있다.
{
private:
	// 1) 접속이 되었을 때 호출되는 함수.
	virtual void	OnConnect() override;
	virtual void	OnDisconnect(uint32_t p_Reason) override;
	virtual	int		OnMessage(CGMSG& _MSG) override;
};

class CGroup : 
	public CGServerGroup::CListSender<CSocket>	// @) List형 Group을 만든다.
{
protected:
	// @) Group에 새로운 멤버가 입장했을 때 호출되는 함수.
	virtual	void	OnMemberEntered(CSocket* /*_pMember*/, CGMSG& /*_MSG*/) override	
	{
		printf("Member Entered\n");
	}

	// @) Group에서 멤버가 나갈 때 호출되는 함수.
	virtual	uintptr_t OnMemberLeaving(CSocket* /*_pMember*/) override
	{
		printf("Member Leaved\n");
			return	0;
	}
};

CGPTR<CGroup>	g_pgroupRoom;

void CSocket::OnConnect()
{
	g_pgroupRoom->EnterMember(this);
}

void CSocket::OnDisconnect(uint32_t /*p_Reason*/)
{
	LeaveGroup();
}

int CSocket::OnMessage(CGMSG& _MSG)
{
	// 1) 네트워크로 전달된 메시지면 Group 전체에게 전송한다.
	if(_MSG.message==CGNETMESSAGE)
	{
		g_pgroupRoom->Send(((CGNETMSG&)_MSG).Buffer);
	}

	return	0;
}

int _tmain(int /*argc*/, _TCHAR* /*argv*/[])
{
	// 1) Group 객체를 생성한다.
	g_pgroupRoom	 = NEW<CGroup>();

	// 2) Group의 Enter가 가능하도록 한다.
	g_pgroupRoom->EnableEnter();

	// 3) Acceptor 객체를 생성한다.
	auto	pacceptor	 = NEW<CGNet::CAcceptor<CSocket>>();

	// 4) 20000번 포트에 Listen을 시작한다.
	pacceptor->Start(20000);

	// 5) ESC키를 누를 때까지 대기한다.
	while(_getch()!=27);

	// 6) Acceptor를 닫는다.
	pacceptor->Stop();

	return 0;
}