gcgc- cgcii 서버 엔진에 적용된 기술 (6) - cgcii server sample

16
Sample Server CGCII Cho sanghyun’s Game Classes II 1. Component of CGCII Server System 2. Simple Server 3. Simple Client 4. Message Sending/Reading 5. Easy to development

Upload: -

Post on 19-Jul-2015

136 views

Category:

Software


1 download

TRANSCRIPT

Page 1: GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample

Sample ServerCGCIICho sanghyun’s Game Classes II

1. Component of CGCII Server System2. Simple Server3. Simple Client4. Message Sending/Reading5. Easy to development

Page 2: GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample

CGCIICho sanghyun’s Game Classes II

실행처리 CGCII Server System (1)

• 접속을 받는 Socket 객체• 접속이 들어오면 내 부적으로 NEW<TSOCKET> 으로 소켓 객체를 생성해서 접속 처

리 !

• Socket 객체

• TSOCKET을 묶어서 관리해줄 객체

// 1) Socket 을 NEW<> 를 사용해서 생성CGPTR<CSocket> pSocket = NEW<CSocket>()…// 2) 접속된 Socket 으로 메시지 전송하려 하면 ..pSocket->Send([ 전송할 내용 ])

// 1) Socket 을 NEW<> 를 사용해서 생성CGPTR<CSocket> pSocket = NEW<CSocket>()…// 2) 접속된 Socket 으로 메시지 전송하려 하면 ..pSocket->Send([ 전송할 내용 ])

• 재정의 가능한 다양한 virtual 로 선언된 훅 함수들이 존재함 .

virtual void OnConnect()→ 접속될 때 호출됨virtual void OnFailConnect() → 접속실패 때 호출됨virtual void OnDisconnect () → 접속 종료될 때 호출됨virtual void OnMessage(…) → 메시지 전송되어 오면 호출됨

Page 3: GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample

CGCIICho sanghyun’s Game Classes II

실행처리

class CSocket :public CGNetSocket::CTCP<>

{private:

virtual void OnConnect() { printf(“ 접속되었다” );}virtual void OnDisconnect() { printf(“ 접속 종료되었다 .”);}virtual DWORD OnMessage(CGMSG& p_rMSG) { printf(“ 메시지 왔다 .”); return TRUE;}

};

class CSocket :public CGNetSocket::CTCP<>

{private:

virtual void OnConnect() { printf(“ 접속되었다” );}virtual void OnDisconnect() { printf(“ 접속 종료되었다 .”);}virtual DWORD OnMessage(CGMSG& p_rMSG) { printf(“ 메시지 왔다 .”); return TRUE;}

};

3. 훅 (Hook) 함수를 재정의 한다 .OnConnect: 접속되었을 때 호출OnDisconnect: 접속종료 되었을 때 호출OnMessage: Message 가 도착했을 때 호출

1. Socket Class 를 상속받는다 .

Server Coding (1)

#include "stdafx.h"#include "Socket.h"

CGOBJ<CGNetAcceptor::CBase<CSocket>> g_acceptor;

int _tmain(int /*argc*/, _TCHAR* /*argv*/[]){

g_acceptor.Listen(20000);

while(_getch()!=27);

return 0;}

#include "stdafx.h"#include "Socket.h"

CGOBJ<CGNetAcceptor::CBase<CSocket>> g_acceptor;

int _tmain(int /*argc*/, _TCHAR* /*argv*/[]){

g_acceptor.Listen(20000);

while(_getch()!=27);

return 0;}

3. Acceptor 선언

4. 20000 번 port Listen 시작

5. ESC 누를 때까지 대기 !

,public NCGPoolable<CSocket>

2. Pool 에서 할당받도록…

Page 4: GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample

CGCIICho sanghyun’s Game Classes II

실행처리 Server Coding (2)

이걸로 서버 동작 ! 특별한 초기화하지 않아도 기본

Thread, Pool, Socket 등등 내부적으로 초기화 처리됨 !

이보다 더 쉬울 수 있나요 ?

Page 5: GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample

CGCIICho sanghyun’s Game Classes II

실행처리

class CSocket :public CGNetSocket::CTCP<>,public CGNetIO::Connector::NTCP

{private:

virtual void OnConnect() { printf(“ 접속되었다” );}virtual void OnFailConnect() { printf(“ 접속실패 !”);}virtual void OnDisconnect() { printf(“ 접속 종료되었다 .”);}virtual DWORD OnMessage(CGMSG& p_rMSG) { printf(“ 메시지 왔다 .”); return TRUE;}

};

class CSocket :public CGNetSocket::CTCP<>,public CGNetIO::Connector::NTCP

{private:

virtual void OnConnect() { printf(“ 접속되었다” );}virtual void OnFailConnect() { printf(“ 접속실패 !”);}virtual void OnDisconnect() { printf(“ 접속 종료되었다 .”);}virtual DWORD OnMessage(CGMSG& p_rMSG) { printf(“ 메시지 왔다 .”); return TRUE;}

};

3. OnFailConnect() 추가 . 나머지는 똑같음 .

1. 동일하게 Socket Class 를 상속받는다 .

Client Coding (1)

#include "stdafx.h"#include "Socket.h"

CGOBJ<CSocket> g_socket;

int _tmain(int /*argc*/, _TCHAR* /*argv*/[]){

g_socket.Connect(“localhost”, 20000);

while(_getch()!=27);

return 0;}

#include "stdafx.h"#include "Socket.h"

CGOBJ<CSocket> g_socket;

int _tmain(int /*argc*/, _TCHAR* /*argv*/[]){

g_socket.Connect(“localhost”, 20000);

while(_getch()!=27);

return 0;}

4. Socket 선언

5. local host:20000 번에 접속 시도한다 .

2. IConnector 도 상속받는다 .(Connect 기능을 위해 )

CGExecutor::Default::InitInstance(CGEXECUTOR_NOTHREAD);

for(;;){

CGExecutor::Default::RunExecutor();

if(_kbhit()==1 && _getch()==27) break;}

Ex2) No-Thread 이므로 매번 호출해주어야 함 !

Ex1) No-Thread 로 동작하기 위한 설정 !( 이걸 설정하지 않으면 자체 Thread 를 생성해서 처리됨 .)

6. ESC 누를 때까지 대기 !

No Thread 로 동작시키고 싶다면 ?No Thread 로 동작시키고 싶다면 ?

역시 끝

Page 6: GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample

CGCIICho sanghyun’s Game Classes II

실행처리

접속 때 MESSAGE_CHATTING 메시지를 전송하게 하려면…

void CSocket::OnConnect(){

CCGBuffer bufSend = MEM_POOL_ALLOC(1024);

bufSend.Append<WORD>();bufSend.Append<WORD>(MESSAGE_CHATTING);bufSend.Append<int>(5);bufSend.AppendString<char>(“Hello CGCII World”);bufSend.SendMessageLength();

Send(bufSend);}

void CSocket::OnConnect(){

CCGBuffer bufSend = MEM_POOL_ALLOC(1024);

bufSend.Append<WORD>();bufSend.Append<WORD>(MESSAGE_CHATTING);bufSend.Append<int>(5);bufSend.AppendString<char>(“Hello CGCII World”);bufSend.SendMessageLength();

Send(bufSend);}

1. CCGBUFFER 에 메모리를 할당한다 .

Message Sending (1)

2. Append 를 사용해서 전송할 메시지를 작성한다 .

3. 전송한다 .

Page 7: GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample

CGCIICho sanghyun’s Game Classes II

실행처리

구조체로 써넣는 방법은 기본적으로 지원한다 .

void CSocket::OnConnect(){

SMESSAGE_TEST temp;temp. sizeMessage = sizeof(SMESSAGE_TEST);temp. wMessage = MESSAGE_TEST;temp. iValue = 5;

CCGBuffer bufSend = MEM_POOL_ALLOC(sizeof(SMESSAGE_TEST));

bufSend.Append<SMESSAGE_TEST>(temp);

Send(bufSend);}

void CSocket::OnConnect(){

SMESSAGE_TEST temp;temp. sizeMessage = sizeof(SMESSAGE_TEST);temp. wMessage = MESSAGE_TEST;temp. iValue = 5;

CCGBuffer bufSend = MEM_POOL_ALLOC(sizeof(SMESSAGE_TEST));

bufSend.Append<SMESSAGE_TEST>(temp);

Send(bufSend);}

Message Sending (2)

1. struct 를 선언해 값을 설정

2. Append 로 한번에 써넣는다 .

3. 전송한다 .

struct SMESSAGE_WELCOME{

WORD sizeMessage;WORD wMessage;int iValue;

};

struct SMESSAGE_WELCOME{

WORD sizeMessage;WORD wMessage;int iValue;

};

Page 8: GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample

CGCIICho sanghyun’s Game Classes II

실행처리

Stream I/O 형식으로 써넣는 방법도 지원한다

Message Sending (3)

void CSocket::OnConnect(){

CCGBuffer bufSend = MEM_POOL_ALLOC(32);

bufSend<<WORD()<<WORD(MESSAGE_CHATTING)<<int(5)<<“Hello CGCII World!!”<<SET_MESSAGE_LENGTH();

Send(bufSend);}

void CSocket::OnConnect(){

CCGBuffer bufSend = MEM_POOL_ALLOC(32);

bufSend<<WORD()<<WORD(MESSAGE_CHATTING)<<int(5)<<“Hello CGCII World!!”<<SET_MESSAGE_LENGTH();

Send(bufSend);}

void CSocket::OnConnect(){

Send(CCGBuffer(MEM_POOL_ALLOC(32)) <<WORD()<<WORD(MESSAGE_CHATTING)<<int(5)<<“Hello CGCII World!!”<<SET_MESSAGE_LENGTH());}

void CSocket::OnConnect(){

Send(CCGBuffer(MEM_POOL_ALLOC(32)) <<WORD()<<WORD(MESSAGE_CHATTING)<<int(5)<<“Hello CGCII World!!”<<SET_MESSAGE_LENGTH());}

한줄로…

void CSocket::OnConnect(){

CCGBuffer(MEM_POOL_ALLOC(32)) <<WORD()<<WORD(MESSAGE_CHATTING)<<int(5)<<“Hello CGCII World”<<SET_MESSAGE_LENGTH() >> SEND(this);}

void CSocket::OnConnect(){

CCGBuffer(MEM_POOL_ALLOC(32)) <<WORD()<<WORD(MESSAGE_CHATTING)<<int(5)<<“Hello CGCII World”<<SET_MESSAGE_LENGTH() >> SEND(this);}

Page 9: GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample

CGCIICho sanghyun’s Game Classes II

실행처리

받은 MESSAGE_WELCOME 메시지를 읽기…

void CSocket::OnMessage(CGMSG& p_rMSG){

CGNETMSG& rMSG = (CGNETMSG&) p_rMSG;

CCGMemoryPtr ptrBuffer = p_rMSG.Buffer;

WORD wSize = ptrBuffer.ExtractHead<WORD>(); WORD wMessage = ptrBuffer.ExtractHead<WORD>();int iValue = ptrBuffer.ExtractHead<int>();const char* strValue = ptrBuffer.ExtractHeadString<char>();

…}

void CSocket::OnMessage(CGMSG& p_rMSG){

CGNETMSG& rMSG = (CGNETMSG&) p_rMSG;

CCGMemoryPtr ptrBuffer = p_rMSG.Buffer;

WORD wSize = ptrBuffer.ExtractHead<WORD>(); WORD wMessage = ptrBuffer.ExtractHead<WORD>();int iValue = ptrBuffer.ExtractHead<int>();const char* strValue = ptrBuffer.ExtractHeadString<char>();

…}

1. CGNETMSG 로 Casting 한다 .

Message Reading (1)

2. 임시 포인터를 선언해 Buffer 의 포인터를 넣는다 .

3. 값들을 Extract 해낸다 .

Page 10: GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample

CGCIICho sanghyun’s Game Classes II

실행처리

Offset 을 알 경우 바로 값을 읽을 수 있다 .

void CSocket::OnMessage(CGMSG& p_rMSG){

CGNETMSG& rMSG = (CGNETMSG&) p_rMSG;

WORD wSize = rMSG .Buffer.Head<WORD>(0);WORD wMessage = rMSG .Buffer.Head<WORD>(2);int iValue = rMSG .Buffer.Head<int>(4);const char* strValue = rMSG .Buffer.GetHeadString<char>(8);

…}

void CSocket::OnMessage(CGMSG& p_rMSG){

CGNETMSG& rMSG = (CGNETMSG&) p_rMSG;

WORD wSize = rMSG .Buffer.Head<WORD>(0);WORD wMessage = rMSG .Buffer.Head<WORD>(2);int iValue = rMSG .Buffer.Head<int>(4);const char* strValue = rMSG .Buffer.GetHeadString<char>(8);

…}

Message Reading (2)

내부 포인터를 옮기지 않고 직접 읽기 .Offset 을 알면 직접 값을 읽을 수 있다 .

Page 11: GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample

CGCIICho sanghyun’s Game Classes II

실행처리 개발하기 쉽다란 ? (1)

그렇다면진짜 개발이 쉽다란 ?

진짜 이보다 더 쉬울 수 있을 까요 ?

Of Course!

문법적으로 더 간결한 코드로 구현이 가능하다 ?→ 원초적 도구 논쟁 JAVA, C++, C# 등등 …

Page 12: GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample

CGCIICho sanghyun’s Game Classes II

실행처리 개발하기 쉽다란 ? (2)

→ 필요한 기능이 구현된 풍부한 라이브러리가 있다 .→ 검증된 코드와 충분한 참고자료가 존재한다 .

→ 경력자의 입장에서는 익숙함 !→ 초보자의 입장에서는 대세 개발 방법이 뭐냐 ?

∵ 기타 디버깅이 쉽다 , 안정적이다 , 싸다 등등은 각자 결론 정해놓고 좋을 대로 끼워맞추는 용도 !

대부분은 기능의 문제에 관심 !!

한걸음 더 나아가면 심리적 요인 !

사장님의 내면적 요인도 존재 !→ 개발 인력을 쉽게 찾을 수 있나 !→ 개발 리스크는 적은가 ?

→ 기능 구현의 문제가 가장 중요한 문제임을 부정할 순 없음 .

Page 13: GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample

CGCIICho sanghyun’s Game Classes II

실행처리 개발하기 쉽다란 ? (3)

→ 쉬운 개발이란 문법적 간결성의 문제일 수 있다 .

코드가 대여섯 줄이라면…

→ 기능 구현의 문제일 수 있다 .

아주 단순한 기능만 구현하는 프로그래밍이라면…

하지만 게임 서버는 점점 복잡해져만 가고… 문제는 적은 코드 작성의 문제 혹은 기능 구현의 문제가 아닌

→ 보다 단순한 모델인로 파악할 수 있도록 하는 시도 !

→ 복잡성 해결의 문제 !

Page 14: GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample

CGCIICho sanghyun’s Game Classes II

실행처리 개발하기 쉽다란 ? (4)

기존 프로그래밍에 비해 Structured Programming 이 개선한 것은 ?

<Iteration><Selection><Sequence>

→ 생산성 개선은 문법적 간결성이나 재사용성에 대한 것이 아닌 이해 , 수정 , 검증의 개선으로…

→ 소프트웨어를 순차진행 , 선택 , 반복 3 요소의 직렬화 만으로 설계하는 것이 핵심 .

CallCall

Return

Return

인지의 흐름

Page 15: GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample

CGCIICho sanghyun’s Game Classes II

실행처리 개발하기 쉽다란 ? (5)

Object Oriented Programming 이 개선한 것은 ?

소프트웨어를 독립된 함수들의 나열이 아니라 객체들 간의 관계로 이해할 수 있도록 해준다 .

Connect (…)Accept (…)SendBuffer (…)SendString (…)ReceiveString (…)Close (…)Open (…)

기능의 나열 프레임워크객체간의 관계

확장성 & 유연성재정의와 합성

• 복잡성 문제 대응 용의• Design Patterns• but 특화문제

조금만 제작된 용도와 다른 용도로 사용하려 하면 오히려 족쇄

• 기능적 문제 해결 수준• 소프트웨어 대형화로 인한 복잡

화문제 대응에 한계

• 객체 조합과 합성 그리고 Generics

• CGCII 는 OOP 와 Generics 를 최대한 활용한 개방적 구조 .

OOP 는 복잡성에 대한 개선에 대한 또 다른 접근…

Page 16: GCGC- CGCII 서버 엔진에 적용된 기술 (6) - CGCII Server Sample

CGCIICho sanghyun’s Game Classes II

질문 ?예외처리

질문 [email protected]