레이블이 network인 게시물을 표시합니다. 모든 게시물 표시
레이블이 network인 게시물을 표시합니다. 모든 게시물 표시

2009년 11월 5일 목요일

Log Class 설계

● 클래스:Log Class 설계

현재 상태를 사용자에게 정확하고 자세하게 알려줄 수 있는 유일한 도구이다.

 

로그라는 특성상 어느 곳에서든지 사용하기 편하도록 Singleton클래스를 상속받아 전역 단일체 클래스로 만들자

 

로그를 필요한 때에 남기지 못하고 또 정확하게 남기지 못하면 서버가 제대로 동작하고 있는지, 문제는 없는지에 대한 정보를 정확하게 파악할 수 없다.

 

체계 없이 남겨진 로그 정보는 실제 필요한 로그를 찾는데 시간이 오래 걸 릴 뿐만 아니라 그게 대한 정보가 부족해 결국 시스템 부하만 줄 뿐 기능상으로는 유명무실해 진다.

 

1. Log 클래스의 종류를 나누자

- 알림과 오류로 나눠 자신이 원하는 정보를 보다 빨리 찾을 수 있도록 설계 하고

2. Log 클래스의 중요도를 나누자

- 각 종류마다 중요도 LOW, NORMAL, HIGH, CRITICAL등 등급을 나누어 쉽게 정보의 중요성을 파악할 수 있게 하자

2-1. 아래 나와 있는 enumLogInfoType은 Log클래스에서 사용할 로그 정보의 분류를 나열한 것이다

enum enumLogInfoType

{

    LOG_NONE= 0x00000000,

    LOG_INFO_LOW= 0x00000001,

    LOG_INFO_NORMAL= 0x00000002,

    LOG_INFO_HIGH= 0x00000004,

    LOG_INFO_CRITICAL= 0x00000008,

    LOG_INFO_ALL= 0x0000000F,

    LOG_ERROR_LOW= 0x00000010,

    LOG_ERROR_NORMAL= 0x00000020,

    LOG_ERROR_HIGH= 0x00000040,

    LOG_ERROR_CRITICAL= 0x00000080,

    LOG_ERROR_ALL= 0x00000100,

    LOG_ALL= 0x000001FF

};

각 등급마다 16진수로 설정하고 OR 연산을 할 수 있도록 2의n승으로 증가시킨다.

- 로그를 저장할 매체 : 파일, 출력 창, 윈도우, DB, TCP, UDP로 분류

enum enumLogStorageType

{

    STORAGE_F ILE= 0x00000000,

    STORAGE_DB= 0x00000001,

    STORAGE_WINDOW= 0x00000002,

    STORAGE_OUTPUTWND= 0x00000003,

    STORAGE_UDP= 0x00000004,

    STORAGE_TCP= 0x00000005

};

위의 enumLogStorageType은 로그를 저장할 매체에 대한 선언이다.

 

로그의 부하로 인해 속도에 문제가 생길 수 있기 때문에 최소한의 처리(로그를 내부 Queue에 넣고 바로 반환)만 하고 내부적으로 틱 쓰레드를 사용하여 일정 시간마다 Queue에 들어있던 로그를 가져와 처리하도록 한다.

서비스 할 때에는 로그를 최소한으로 하여 사용해야 한다.

 

 

3.로그를 남기는 시점

3-1. 에러 로그의 경우 모든 경우에 로그로 남긴다.

- 쉽게 넘긴 작은 에러 하나가 정말 큰 버그를 부른다.

3-2. 일반적인 정보 로그의 경우

- 함수 시작 부분과 모든 패킷 처리 시작 부분에 남기는 것이 좋다.

- 이유는 만약 어떤 처리를 하다 이유 없이 서버 프로세스가 죽었을 경우에 쉽게 그 위치를 파악할 수 있다.

- 모든 함수와 패킷에서 로그를 남긴다면 실제 서비스할 때에는 엄청난 부하가 생길 것이다. 그래서 앞에서 정한 등급에 따라 일정 등급 이하의 정보를 로그로 남기지 않거나 정보 관련 로그는 아예 남기지 않도록 할 수 있다.

 

4.무엇을 로그로 남길 것인가

4-1. 로그가 어떤 함수에서 남겨졌는지 알아야 한다.

4-2. 누구에 의해서 로그가 남겨졌는지를 알아야 한다.

- 시스템일수도 있고 패킷을 받아 남기는 것이라면 패킷을 보낸 해당 클라이언트가 될 수도 있다.

4-3. 로그가 발생되는 시간을 남겨야한다.

4-4. 로그의 종류가 에러라고 하면 에러가 어떤 작업을 하다가 발생한 것인지 남겨야하고 종류가 알림이라면 함수의 인자나 받은 패킷의 프로토콜 내용을 남겨야 한다.

2009년 10월 26일 월요일

서버 프로그래밍 기초

● 윈도우즈형과 ANSI 표준형의 비교 및 설명

윈도우즈(windows)

ANSI

설명

BOOL

bool

TRUE/FALSE 변수

BYTE

signed char

8비트 변수

DWORD

unsigned long

32비트 정수형 변수

DWORD_PTR

unsigned long

32비트 정수형 포인터 변수

FLOAT

float

32비트 실수형 변수

INT

int

32비트 정수형 변수

INT32

int

32비트 정수형 변수

INT64

_int64

64비트 정수형 변수

CHAR

char

8비트 변수

LPCSTR

const char*

8비트 문자열 변수

LPCTSTR

char* 또는 wchar*

MultiByte,Unicode에 따라 달라짐

VOID

void

 

- LPCTSTR은 CONST TCHAR*를 의미 합니다.

 

● 32bit 환경에서의 데이터형에 따른 바이트 크기

데이터형

크기

설명

INT

4 바이트

 

INT32

4 바이트

 

INT64

8 바이트

64bit INT형으로 8바이트 크기

FLOAT

4 바이트

 

DOUBLE

8 바이트

 

BYTE

1 바이트

 

CHAR

1 바이트

 

WCHAR

2 바이트

Unicode를 표현하기 위한 데이터형

DWORD

4 바이트

 

USHOT

2 바이트

16bit 만큼의 숫자를 표현할 수 있음

SHORT

2 바이트

 

 

● 윈도우즈 함수와 ANSI 함수의 비교 및 설명 (대표적 함수)

윈도우즈(Windows)

ANSI

설명

FillMemory

memset

정해진 크기의 메모리에 데이터를 채울 때 사용

ZeroMemory

memset

정해진 크기의 메모리를 0으로 초기화할 때 사용

CopyMemory

memcpy

정해진 크기의 메모리를 복사할 때 사용

MoveMemory

memmove

정해진 크기의 메모리를 이동할 때 사용

[함수 원형]

VOID FillMemory(PVOID Destination, SIZE_T Length, BYTE Fill)

PVOID Destination

SIZE_T Length

BYTE Fill

값을 채울 메모리입니다.

값을 채울 크기입니다.

채울 1바이트 값입니다.

VOID ZeroMemory(PVOID Destination, SIZE_T Length)

PVOID Destination

SIZE_T Length

초기화할 메모리입니다.

초기화할 크기입니다.

VOID CopyMemory(PVOID Destination, CONST VOID* Source, SIZE_T Length)

PVOID Destination

CONST VOID* Source

SIZE_T Length

복사를 해 넣을 메모리입니다.

복사할 원본 메모리입니다.

복사할 크기입니다.

VOID MoveMemory(PVOID Destination, CONST VOID* Source, SIZE_T Length)

PVOID Destination

CONST VOID* Source

SIZE_T Length

옮겨 넣을 메모리입니다.

옮길 원본 메모리입니다.

옮길 크기입니다.

 

● TCHAR 사용에 따른 문자열 함수

TCHAR

CHAR

설명

_tcscpy

strcpy

문자열을 복사할 때 사용

_tcsncpy

strncpy

문자열을 정해진 길이만큼 복사한다

_tcscmp

strcmp

문자열을 비교 한다

_tprintf

printf

화면에 문자열을 출력 한다

_stprintf

sprintf

정해진 버퍼에 정해진 형식의 문자열을 입력

_sntprintf

snprintf

정해진 버퍼에 정해진 길이만큼 정해진 형식의 문자열을 입력

[함수 원형]

TCHAR* _tcscpy(TCHAR *strDestination, CONST TCHAR *strSource)

RETURN

TCHAR *strDestination

CONST TCHAR *strSource

strDestination의 포인터

문자열을 복사해 넣을 메모리

원본 문자열

TCHAR* _tcsncpy(TCHAR *strDestination, CONST TCHAR *strSource, SIZE_T count)

RETURNT

CHAR *strDestination CONST TCHAR *strSource SIZE_T count

strDestination의 포인터

문자열을 복사해 넣을 메모리

원본 문자열

복사해 넣을 문자열의 길이

INT _tcscmp(CONST TCHAR *string1, CONST TCHAR *string2)

RETURNT

CONST TCHAR *string1 CONST TCHAR *string2

0일 경우 같고 0이 아닐 경우 같지 않은 문자열

비교할 문자열 1

비교할 문자열 2

INT _tprintf(CONST TCHAR *format, [argument])

RETURNT

CONST TCHAR *format

출력된 문자열의 개수

포맷 문자열

INT _stprintf(TCHAR *buffer, CONST TCHAR *format, [argument])

RETURNT

TCHAR *buffer

CONST TCHAR *format

출력된 문자열의 개수

문자열을 입력할 메모리

포맷 문자열

INT _sntprintf(TCHAR *buffer, SIZE_T count, CONST TCHAR *format, [argument])

RETURNT

TCHAR *buffer

SIZE_T count

CONST TCHAR *format

출력된 문자열의 개수

문자열을 입력할 메모리

입력할 문자열의 개수

포맷 문자열

 

2009년 10월 24일 토요일

MMORPG 게임서버 프로그래밍...

----------------------------------------------------------------------------------------

Q>게임 서버에서 각 클라이언트로 브로드캐스팅이라고 하나요?

 

A>시간 간격 및 데이타 갱신: 플레이어를 예를 든다면 움직인 플레이어만 움직인 플레이어만 그 플레이어의 시야거리내에 있는 다른 플레이어에게 브로드캐스팅합니다. 즉, 움직이지 않는다면 보내지 않는것이 좋습니다.

 

만약 일정한 시간간격이라면 상황에 따라  나눌수가 있는데 제 개인적으로는 전투처럼 바로 처리는 100msec 일반적인 이동은 500~1000msec를 설정합니다.

 

Q>얼마정도 인원의 클라이언트에게 제공하는것이 좋은가?

A>플레이어 시야거리내에 있는 모든 사람에게 해야 합니다.

 

위 내용은 MMORPG를 기준으로 합니다.  캐주얼 게임이면 다를게 설정을 해야 합니다.

----------------------------------------------------------------------------------------

A> 책추천 및 테스트 방법

1. Scott meyers 가 쓴 책은 전부 보세요. 정말로 좋습니다->Scott meyers는 천재

2. 최근에 번역되어서 나온 GameCoding Complete

3. Win32 멀티 스레드 프로그래밍

4. Win32 SystemProgramming

5. Gems1~4

6. Windows 구조와 원리 그리고 Codes 등등입니다.

7. MSDN 항상 최신의 것을 설치해서 변경된 것을 보세요

Q> 서버 개발

A> 서버 개발을 할때는 꼭 멀티스레드로 만들어야 합니다. 그리고 테스트는 멀티 프로세서

 기반에서 해야 합니다. 즉, 물리적으로 CPU가 두개인 것을 사용하지 못할때는 HyperThreading에서

 개발 및 테스트를 해야합니다. 그리고 물리적으로 컴퓨터를 따로 설치할 수가 없으면 VMWare와

 같은 OS Emulation 소프트웨어를 이용해서 테스트를 해야 합니다. 같은 로컬에서 클라이언트/서버

 테스트는 될 수 있는대로 안하는게 좋습니다.

 


제 답변이 도움이 되었다니 저도 기쁩니다.^^

 

부담갖지 마시고 질문하세요^^ 제가 아는 한 답변드리겠습니다.^^

단,  제 말이 성경책처럼 항상 옳은게 아니라 실수할 수도 있고 잘못 알고있을 수도 있습니다.

 

Q>혹시 게임서버와 시스템에 관해서 책 좀 추천해 주실 수 있을런지요?
>인테넷 주소도 좋습니다.
>
>저는 현재 경력 1년 좀 넘은 클라이언트 프로그래머입니다.
>아직 미흡한 점이 많고 잘 모르는 부분이 많습니다.
>게다가 정보력도 부족해서 인터넷에서 찾는것도 잘 못하였는데,
>경준님께서 강의해주신 것과 또 강연때 알려주신 웹사이트에서
>많은 도움을 받았습니다. 찾다가 보니 몰랐던 것이 많더군요.. ^^;
>특히 gameai.net인가요 거기서 여러가지를 알게되어 좋았습니다.
>
>다시 한번 감사를 드리며,
>바쁘시다라도 좋은 답변 부탁드립니다.
>그럼 늘 좋은 일만 있으시길 기대하며 이만 줄입니다.
>
>추신: 서버프로그래밍을 집에서 제가 테스트 하려면 어떻게 하는게 좋을런지도 조
>언 부탁드립니다.
>아니면 보다 쉽게 제가 테스트를 할수 있는 방법이 있는지도요.

 

A> 책추천 및 테스트 방법

1. Scott meyers 가 쓴 책은 전부 보세요. 정말로 좋습니다->Scott meyers는 천재

2. 최근에 번역되어서 나온 GameCoding Complete

3. Win32 멀티 스레드 프로그래밍

4. Win32 SystemProgramming

5. Gems1~4

6. Windows 구조와 원리 그리고 Codes 등등입니다.

7. MSDN 항상 최신의 것을 설치해서 변경된 것을 보세요

Q> 서버 개발

A> 서버 개발을 할때는 꼭 멀티스레드로 만들어야 합니다. 그리고 테스트는 멀티 프로세서

 기반에서 해야 합니다. 즉, 물리적으로 CPU가 두개인 것을 사용하지 못할때는 HyperThreading에서

 개발 및 테스트를 해야합니다. 그리고 물리적으로 컴퓨터를 따로 설치할 수가 없으면 VMWare와

 같은 OS Emulation 소프트웨어를 이용해서 테스트를 해야 합니다. 같은 로컬에서 클라이언트/서버

 테스트는 될 수 있는대로 안하는게 좋습니다.

 

그럼 즐거운 오후 보내세요


 

 

----------------------------------------------------------------------------------------

Q>1. VMWare와 같은 OS Emulation 소프트웨어를 사용하면 한 pc에서 서버와 클라이
언트를 동시에 사용가능하단 말씀인지요?

 

A> 네 VMWare 3.0이상을 사용하시면 OS 설치후 네트워크 아이피로 새로 하나 할당

할 수있습니다. 즉, 한 PC에 완전히 분리된 새로운 OS가 작동합니다.

 

Q>2.서버의 예제 소스들이 있는 사이트가 있을까요? 보통 채팅 예제들은 있던데

A>으로 게임서버로 확장이 가능한지요? 전부다 나와있는 사이트는 없습니다.

다만 "MMORPG Game Server Programming for Linux"라는 책에 기본동작하는 완벽한

예제 코드가 있습니다.

 

Q>3. 또한 서버는 db와 연동된다고 들었습니다. db는 어떻게 연동이 되는건지요?

A> 저는 주로 MS-SQL  2000을 이용합니다. 일반적으로 ODBC,ADO를 사용합니다.

솔직히 DB는 VisualC++ 연결해서 쿼리 또는 StoredProc를 호출하는 수준입니다.

이부분은 저도 약합니다.ㅠㅠ

----------------------------------------------------------------------------------------

Q> 크리티컬 섹션의 단점?

A> 우선 윈도우의 4가지 동기화 객체를 확실히 알고 프로그램 하시기를 권장합니다.

저도 예전에는 거의 CriticalSection을 사용했습니다. 솔직히 CriticalSection이 직관적이고

사용하기가 쉽습니다.

그리고 CriticalSection은 동기화 객체중 속도가 가장 빠르다는 장점이 있습니다.

 

CriticalSection은 커널 객체가 아닙니다.

즉, 커널이 관리하지 않습니다.

그래서 만약 CriticalSection에서 Enter한 후에 그 스레드가 정지하면

DeadLock에 빠집니다.

스레드는 커널에서 관리하기 때문에 스레드는 커널에서 지워서 없애버리지만

CriticalSection은 커널이 관리 하지 않아서 데드락에 빠집니다.

실제로 이런 버그가 발생하면 잡는것도 어렵습니다. 왜냐하면 프로세스는 죽지않고

스레드만 멈추어서 외부에서는 알아차리기가 어렵습니다.

 

또 한가지는 시간 설정입니다. 즉 뮤텍스를 사용하면 WaitForSingleObject API

를 사용해서 스레드 내에서 함수 호출 시간을 관리 할 수있습니다. 만약 100msec안에

처리 못한다면 다른 스레드에 제어권을 넘기거나 하는 여지가 있습니다.

그러나 CriticalSection은 불가능 하죠.

 

분명히 CriticalSection은 잘만 사용하면 강력합니다.

제가 권장하는 것은 최대한 짧게 CriticalSection을 사용하는 것입니다.

 

제가 생각하는 CriticalSection장단점입니다.

----------------------------------------------------------------------------------------