목록Categories (1099)
KoreanFoodie's Study
[C++ 게임 서버] 6-1. 채팅 실습 핵심 : 1. Chat 서버를 만들어보자. 간단하게는 채팅이 전파될 Room 과 채팅 패킷만 만들어 주면 된다. 2. 채팅을 전파할 때마다, Room 에서 WRITE_LOCK 을 잡으면 병목현상이 생길 수 있다. 이를 해결하기 위해, 추후 JobQueue 를 도입할 것이다. 이번에는 채팅 패킷을 만들어 보면서, 간단하게 실제로 패킷을 추가하는 작업을 어떻게 진행하는지 살펴볼 것이다. 일단, 우리가 작업했던 Protocol.proto 를 다음과 같이 수정해 주자. syntax = "proto3"; package Protocol; import "Enum.proto"; import "Struct.proto"; message C_LOGIN { } message S_LOG..
[C++ 게임 서버] 5-9. 패킷 자동화 #2 핵심 : 1. 파이썬과 jinja2 를 이용해, 패킷 핸들러 코드를 자동으로 생성해 보자. 2. 이 포스팅에서 만든 ProtoParser 는 Protocol.proto 의 패킷 명세를 읽어 PacketHandler 의 코드를 자동으로 생성한다. 저번 시간에 패킷 자동화를 위한 밑작업(?) 을 보여준 바 있다. 사실 제대로 패킷 자동화를 구축하기 위해서는, data-driven 하게 작업이 이루어져야 할 것이다. 간단한 Flow 를 생각하면 다음과 같다 : Protocol.proto 에 우리가 원하는 패킷(메시지)을 선언한다. 자동화 툴이 돌아가서 Packet 과 PacketHandler 클래스를 생성한다. 프로그래머는 각 패킷에 대한 커스텀 동작만 직접 구..
[C++ 게임 서버] 5-8. 패킷 자동화 #1 핵심 : 1. 효율적인 작업을 위해, 패킷이 변동될 때 빌드를 하면 관련 protoc 파일 등이 자동으로 업뎃되게 만들면 좋다. 배치파일과 .vcxproj 를 잘 수정해 보자. 2. 초기화 단계에서 각 패킷 별로 호출되어야 하는 함수를 Functor 로 만들어 각 패킷에 대응시켜 놓으면, 각 컨텐츠 담당자는 패킷이 추가될 때 해당 패킷에 대한 구현만 신경쓰면 된다. 저번 시간에는 Protobuf 를 세팅하면서, 패킷 작업을 어떻게 하면 되는지에 대해 배웠다. 그런데 사실 돌이켜 보면 불편한 점이 이곳 저곳에 산재한다는 느낌이 든다. 왜냐하면 결국 우리가 패킷을 만들거나 수정하면, .protoc 파일을 매번 새로 생성해 줘야 하는데, 심지어 이 작업을 Gam..
[C++ 게임 서버] 5-7. Protobuf 핵심 : 1. protobuf 는 구조화된 데이터를 직렬화하는 방식으로, 구글에서 제공하는 툴을 의미하기도 한다. 2. protobuf 를 사용하면 임시 객체에 대한 복사는 발생할 수도 있으나, 직렬화와 역직렬화 과정이 매우 편리해진다는 장점이 있다. 3. protobuf 는 인터페이스가 간단하고 명확하며, 다른 언어 및 OS 를 사용하는 타 서버와의 연동이 쉬워 협업에도 매우 유리하다. 이번 시간에는 구글에서 만든 데이터 직렬화 툴을 지금까지 만든 샘플 프로젝트에 적용해 볼 것이다. 이번에는 결과만 보여주는 것이 아니라, 설치 및 세팅하는 과정을 자세히 기록할 것이니, 추후 세팅에 어려움을 겪을 때 이 글이 도움이 되었으면 좋겠다. 🤗 먼저, protobu..
[C++ 게임 서버] 5-6. 패킷 직렬화 #3 핵심 : 1. 가변 데이터 안에 가변 데이터를 넣는 경우도, 결국 Offset 과 Count 를 이용해 버퍼에 데이터를 기록하는 방식으로 처리한다. 2. 추후에 소개할 ProtoBuf 를 이용하면, 패킷을 만들 때 가변 데이터를 일일히 코드로 넣는 귀찮음을 줄일 수 있다(다만 불필요한 복사가 있을 수는 있음). 저번에는 가변 데이터를 패킷에 넣어 보았는데... 만약 가변 데이터 안에 또 가변 데이터가 있다면 어떻게 해야 할까? 예를 들어, BuffListItem 이라는 구조체에 해당 버프의 대상들 정보(Victims 라고 하자)를 담는다면 어떻게 해야 할까? struct BuffsListItem { uint64 buffId; float remainTime;..
[C++ 게임 서버] 5-5. 패킷 직렬화 #2 핵심 : 1. 가변 데이터를 처리할 수 있는 PacketList 를 만들면, 버퍼를 읽을 때 임시 객체를 생성하지 않고 캐스팅을 통해 데이터를 효과적으로 읽어들일 수 있다. 자, 일단 저번 시간에는 가변 데이터 형식인 buffs 에 대해 패킷 직렬화를 수행했었다. 그런데 코드를 잘 보면, 조금 마음에 들지 않는 부분이 있다. vector buffs; buffs.resize(pkt.buffsCount); for (int32 i = 0; i > buffs[i]; 바로 buffs 데이터를 읽을 때 임시 객체가 생성되는 것인데... 생각해보면 굳이 그럴 필요가 있나 싶다. 🤔 이 부분을 최적화하기 위해, 이번 글에서..
[C++ 게임 서버] 5-4. 패킷 직렬화 #1 핵심 : 1. 패킷 직렬화란, 포인터 및 가변 데이터 정보를 패킷으로 주고 받을 때 이를 안전하게 저장하고 불러올 수 있도록 파싱하는 기법이다. 2. 가변 데이터의 경우, Offset 과 Count 를 이용해 직렬화를 쉽게 진행할 수 있다. 3. 직렬화된 데이터는 xml 또는 json 포맷으로 세이브 & 로드를 하며 관리하게 된다. xml 은 가독성이 좋을 수 있으나 복잡하며, json 은 형태가 간단하며 파싱 속도가 빠르다. 이번 글에서는 패킷 직렬화에 대해 알아보자. 영어로는 사실 Serialization 인데, 직렬화라고 하니 살짝 어색하게 느껴지기는 한다. 😅 언리얼에서도 Serialization 이라는 용어를 사용하는데, 그 때는 데이터를 안전하고..
[C++ 게임 서버] 5-3. Unicode 핵심 : 1. 문자열을 핸들링에는 2가지 요소가 있다. 하나는 Character Set 이고, 다른 하나는 Encoding 이다. 2. Unicode 는 다양한 문자열에 대응할 수 있는 Set 으로, 인코딩 방식에 따라 UTF-8 이나 UTF-16 등으로 나뉘게 된다. 3. MBCS 는 문자의 특징마다 사용하는 바이트가 다른 경우를 의미하며, WBCS 은 모든 문자열이 동일한 바이트를 사용하는 방식이다. 이번 글에서는 누구나 익숙하지만 물어보면 항상 헷갈리는 내용, 유니코드에 대해 다시 짚고 넘어가도록 하겠다. 일단 Unicode 에 대해 제대로 이해하려면 문자열 인코딩의 두 요소, 'Character Set' 과 'Encoding' 을 구분해야 한다. 먼저,..
[C++ 게임 서버] 5-2. PacketHandler 핵심 : 1. 다양한 패킷에 대한 처리를 대응하기 위해서, 패킷별로 enum 을 만들고, 각 enum 별로 패킷을 핸들링하는 함수를 만들어 주면 switch 문으로 한번에 처리할 수 있을 것이다. 2. 가변 데이터를 넣는 경우도 Primitive Type 을 읽는 경우와 거의 비슷하다. 벡터의 크기나 갯수 정보를 넣어주기만 하면 해결된다! 이전 시간에는 Buffer Helper 클래스를 만들어 버퍼를 조금 더 용이하게 읽고 쓸 수 있도록 했다. 하지만 아직 부족하다! 일일히 임의의 값으로 버퍼의 내용을 채워 패킷을 조립하고 분해하는 것보다, 좀 더 정형화된 형태로 패킷을 주고 받을 수 있는 것이 좋다. 그래서 이번 글에서는 PacketHandler ..
[C++ 게임 서버] 5-1. BufferHelper 핵심 : 1. Buffer 를 쉽게 읽고 쓸 수 있게 해 주는 Buffer Helper 클래스를 만들어 보자. 2. '>>' , '>' 를 오버로딩한 부분이다. 현재 버퍼에서 읽을 부분을 적절한 타입으로 캐스팅해 읽어낸 후, _pos 를 이동시키면, 연속해서 '>>' 연산을 수행할 수 있다. 실제 예시는 아래 부분에 DummyClient 클래스를 통해 확인할 수 있을 것이다 😄 BufferReader.cpp BufferReader::BufferReader() { } BufferReader::BufferReader(BYTE* buffer, uint32 size, uint32 pos) : _buffer(buffer), _size(size), _pos(po..