WinCNT

데이터 드리븐과 메시지 큐 본문

게임 프로그래밍(학습 내용 정리)/네트워크 프로그래밍

데이터 드리븐과 메시지 큐

WinCNT_SSS 2022. 5. 9. 12:29

네트워크 프로그래밍서버 프로그래밍이란?

게임 서버를 만든다는 것게임 서비스란?

네트워크 게임온라인 게임이란?

OOP과 메시지 큐

객체 간의 관계가 있고 서로 통신한다

객체에 큐를 달고 보내고 싶은 메시지를 Send하면 된다

 

예를 들어 네트워크에서 클래스ID와 Move를 받았으면

바로 Move를 호출하는 것이 아니라

해당 클래스 객체의 메시지 큐에 Move라는 메시지를 push할 뿐!!

 

객체는 주어가 될 수 있으며, 능동적일 수도 있고 수동적일 수도 있다

(데이터는 목적어)

객체 간의 통신은 큐에 메시지를 넣는 방식을 취한다

데이터를 어떻게 처리할 것인가?

클라 <--> 서버

요청과 응답

클라이언트와 서버의 관계

극단적인 예

1. 서버가 없는 싱글 게임인 경우

2. 클라는 터미널 역할만 하고 나머지 모든 것은 서버에서 하는 경우

ex) PARSEC과 같은 게임 스트리밍, GPU 연산까지도 서버에서 하는 경우

 

보통은 그 사이의 배분 구조를 디자인 함

 

요청을 하고 응답 값을 처리, 결과 - 동기화는 확실하지만 반응성이 떨어짐

일단 처리하고 통보하고 허락을 받음 - 반응성은 좋지만 동기화가 불확실해짐

 

중요한 것은 Trade-Off이다

FPS는 오픈 소스는 있으니 잘 참고하고, MMORPG는...열심히 생각해보자

그리고 이러한 부분은 튜닝이므로 스텝 바이 스텝으로 잘 짜보자

패킷이란 데이터를 받아서 어떻게 처리할 것인가

패킷: 네트워크에서 주고 받는 데이터

 

수신 버퍼에 들어오는 데이터는 바이트 스트림

(char*로 넘기지만 문자형이 아니라 1바이트로 받는 것)

응용 프로그램에서의 프로토콜 정의

1. 프로토콜 정의는 왜 필요한가

데이터를 주고 받기 위해

프로토콜, 파싱

바이너리 형태의 프로토콜(struct)과 텍스트 형태의 프로토콜(string, text)이 존재한다

msgProtocol.h	// 헤더 파일 하나 만든다
struct HEADER
{
    INT16 size;
    INT16 id;
}

struct MSG_CHAT : HEADER
{
    char msg[MAX_LEN];
}

2. 버퍼 관리

버퍼는 Read Index(응용단에서 해석하고 남은 데이터의 인덱스)와

Write Index(수신 버퍼에서 읽어온 데이터를 응용단 버퍼에 채울 인덱스)로 해야 한다

메모리는 옮기거나, 환영 큐로 만들어서 버퍼가 꽉 차는 것을 막는다

 

네트워크 객체와 프로세스 객체를 분리하려면

누가 처리할 것인지를 잘 판단해야 한다

(패킷을 수신하고 메시지 큐에 넣는 등)

수업 내용 정리

1. 사용자 정의 프로토콜

패킷 구조를 정의한다

> 바이너리 타입 - 구조체 정의를 통한 캐스팅 : 케임 프로토콜은 대부분 바이너리 타입

> 텍스트 타입, 문자열 파싱 : 게임 서비스에서도 사용(웹 서버(자바 등) 쪽과 연동(인증, 빌링))

 

각각의 장단점은 무엇일까?

바이너리 타입 : 작고 빠르지만 유연성이 떨어진다(이기종 간의 이식 등)

텍스트 타입 : 유연성은 좋지만 무겁고 느리다, 인코딩 문제도 조심해야 한다

 

바이너리 타입인 경우는 구조체이기 때문에 정렬(Alignment) 문제가 있다

Alignment를 1로 해서 구조체를 캐스팅해서 읽고 쓰는 게 빠르고 쉽다

 

구조체의 중간에 가변 인자가 있는 경우는

시리얼라이즈, 디시리얼라이즈를 사용해도 된다(유연성 업)

(직접 구현해도 되고, 요즘은 구글의 플랫 버퍼을 쓰기도 한다)

2. 패킷 조립 -> 수신 : 바이트 스트림(char*) --> 패킷

수신 데이터는 바이너리 스트림 데이터

사용자 정의 프로토콜 헤더를 해석해서 패킷 사이즈와 패킷 아이디(혹은 코드) 분석

 

> 바로 처리할 것인가

> 네트워크 객체와 로직 개체를 분리하기 위해 --> 큐를 사용 --> 다른 객체에 책임 전가

(단일 책임의 원칙, OOP에서 매우 중요)

3. 패킷 조립 --> 송신 : 패킷 --> 바이트 스트림(char*)

로직단에서는 PostPacket 등의 송신 패킷을 만들어서 송신 큐에 넣어두기

네트워크 단에서는 송신 패킷 큐에서 패킷을 가져다가 송신한다

 

SSS