LOGIN • JOININ

MESSAGE MAP

[Tutorials/[Network] 1. Socket classes/Server/Tutorial_SocketServer03_MessageMap]



서버가 전달받는 메시지의 종류가 많다면 if문이나 switch문의 나열로 작성해 주어야 합니다.

이 것을 좀더 편리하게 정의할 수 있도록 하기 위해 MESSAGE_MAP을 사용할 수 있습니다.

MESAAGE_MAP을 사용하기 위해서는 3가지의 작업만 하면 됩니다.


① 클래스 정의에 ‘DECLARE_CGMESSAGE_MAP ‘ 추가

② 메시지 맵의 작성

③ OnMessage()함수에서 메시지 맵 호출하기


1... 클래스 정의에 ‘DECLARE_CGMESSAGE_MAP’추가

간단히 클래스의 아무 위치에나 ‘DECLARE_CGMESSAGE_MAP’만 써넣어 주면 됩니다. 

class CSocket : public CGNet::Socket::CTCP<>
{
protected:
	virtual void OnConnect() override;
	virtual void OnDisconnect(uint32_t) override;

	DECLARE_CGMESSAGE_MAP	// @) 이것 추가!!

	virtual int OnMessage(CGMSG& _MSG) override;

			int	OnMessage_A(CGNETMSG& _MSG);
			int	OnMessage_B(CGNETMSG& _MSG);
			int	OnMessage_C(CGNETMSG& _MSG);
};


2... 메시지 맵은 메시지와 함수의 맵핑을 정의해 주면 된다.

BEGIN_CGMESSAGE_MAP(CSocket)
	CGMESSAGE_TYPE_SUB(CGNETMESSAGE, ((CGMSG_BUFFER&)_MSG).Buffer.front<uint32_t>(4))
		ON_CGMESSAGE(MESSAGE_SEND_A, OnMessage_A, CGNETMSG);
		ON_CGMESSAGE(MESSAGE_SEND_B, OnMessage_B, CGNETMSG);
		ON_CGMESSAGE(MESSAGE_SEND_C, OnMessage_C, CGNETMSG);
	END_SUB_CGMESSAGE_MAP
END_CGMESSAGE_MAP

MESSAGE_SEND_A, MESSAGE_SEND_B, MESSAGE_SEND_C는 각각 OnMessage_A(), OnMessage_B(), OnMessage_C()함수에 맵핑되었습니다.



3... OnMessage()함수에서 메시지 맵 호출하기

간단히 OnMeessage() 함수에 EXECUTE_CGMESSAGE_MAP(_MSG)만 써주면 됩니다.

int CSocket::OnMessage(CGMSG& _MSG)
{
	EXECUTE_CGMESSAGE_MAP(_MSG); // @) Message Map을 호출한다.

	return	0;
}

EXECUTE_CGMESSAGE_MAP(_MSG)는 메시지 맵에 정의된 함수가 호출해 줍니다.



[TutorialSocketServerMessageMap.cpp]
#include "stdafx.h"
#include "CGNetSocketTemplates.h"

const uint32_t	MESSAGE_SEND_A	 = 0x00000020;
const uint32_t	MESSAGE_SEND_B	 = 0x00000021;
const uint32_t	MESSAGE_SEND_C	 = 0x00000022;

class CSocket : public CGNet::Socket::CTCP<>
{
protected:
	// 1) Hook 함수들
	virtual void OnConnect() override;
	virtual void OnDisconnect(uint32_t) override;

	// @) 이것 추가!!
	DECLARE_CGMESSAGE_MAP

	virtual int OnMessage(CGMSG& _MSG) override;

	// @) Message별 처리 함수 추가!
			int	OnMessage_A(CGNETMSG& _MSG);
			int	OnMessage_B(CGNETMSG& _MSG);
			int	OnMessage_C(CGNETMSG& _MSG);
};

void CSocket::OnConnect()
{
	printf("Connected\n");
}

void CSocket::OnDisconnect(uint32_t)
{
	printf("Disconnected\n");
}

// @) Message Map을 정의한다!
BEGIN_CGMESSAGE_MAP(CSocket)
	CGMESSAGE_TYPE_SUB(CGNETMESSAGE, ((CGMSG_BUFFER&)_MSG).Buffer.front<uint32_t>(4))
		ON_CGMESSAGE(MESSAGE_SEND_A, OnMessage_A, CGNETMSG);
		ON_CGMESSAGE(MESSAGE_SEND_B, OnMessage_B, CGNETMSG);
		ON_CGMESSAGE(MESSAGE_SEND_C, OnMessage_C, CGNETMSG);
	END_SUB_CGMESSAGE_MAP
END_CGMESSAGE_MAP

int CSocket::OnMessage(CGMSG& _MSG)
{
	// @) Message Map을 호출한다.
	EXECUTE_CGMESSAGE_MAP(_MSG);

	return	0;
}

int CSocket::OnMessage_A(CGNETMSG& /*_MSG*/)
{
	printf("Message A (" __FUNCTION__ ")\n");
	return	1;
}

int CSocket::OnMessage_B(CGNETMSG& /*_MSG*/)
{
	printf("Message B (" __FUNCTION__ ")\n");
	return	1;
}

int CSocket::OnMessage_C(CGNETMSG& /*_MSG*/)
{
	printf("Message C (" __FUNCTION__ ")\n");
	return	1;
}

int _tmain(int /*argc*/, _TCHAR* /*argv*/[])
{
	// 1) Acceptor 객체를 생성한다.
	auto	pacceptor	 = NEW<CGNet::CAcceptor <CSocket>>();

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

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

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

	return 0;
}