묻고 답해요
156만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
MakeShared 함수 관련
52강 ServerService 수강 중 13:54 때에 MakeShared함수를 이용해서 shared_ptr을 생성해주는 부분이 있는데, 똑같이 따라하던 중 제 프로젝트에서 컴파일 에러가 발생했습니다.첨부해주신 프로젝트와 비교해보니 MakeShared함수가 변경되어 있더라구요기존에 Memory 관련 강의 이후에는 변경된점이 없어서 어느 시점에 변경된건지 궁금합니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
지금까지 서버코어에서 만든 내용에 대해 궁금한 점이 있어서 질문 드립니다.
지금까지 개발한 서버코어는 IOCP기반의 비동기 논블로킹 방식이라 생각됨니다.Send에서는 SendBuffer를 sendEvent에 등록한 다음 Scatter-Gather로 모아서 ::WSASend로 송신을 수행하는 것으로 이해했습니다.Recv에서는 ::WSARecv에서 수신을 받기 전에 버퍼에 패킷 데이터를 조립한 다음에 바로 함수를 실행하고 있습니다.이벤트 데이터는 사실상 비어있고 callback함수도 없으니 ::WSARecv는 수신완료를 CP에 보내는 것 밖에 없다고 봅니다.제가 볼때 수신부는 제가 이해한 비동기 방식과는 다르게 돌아가는 것 같습니다.어떻게 이해해야 할까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
운영체제관련 질문입니다
운영체제도 같이 공부를 하고싶어 소위 공룡책이라는 운영체제책을 사서 공부를 하고있습니다 운영체제를 처음부터 만들어보는 실습 책들을 따라해보면 이라고 하셨는데 어떤책을 추천해주시는지 알수있을까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
send하려는 데이터 크기가 크면 memcpy에서 문제가 발생할 것 같습니다.
여기서 만약 복사 시작지점 + len 이 array 범위 밖이면 sendBuffer->Close(len) 안에서ASSERT_CRASH(_allocSize >= len); 으로 체크하기 전에 array 정적배열에 memcpy를 하니까 이 부분에서 문제가 생길 것 같습니다.OnRecv로 들어온 buffer가 6001바이트짜리 라면 Open(4096)이 성공하고, 6000크기의 배열에 6001크기를 memcpy 하니 오버플로우가 일어날 것 같습니다.아니면 Open(4096)으로 chunk로부터 사용할 수 있는 공간을 할당 받을 때 len이 4096보다 반드시 작을거라는 확신이 있기 때문에 memcpy 전에 확인하지 않는건가요?
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
Snapshot base vs packet oriented
Hello Master 🙂I would like to ask wich method is prefered in wich case. Most mmo code i seen either go packet way like in this course or Client send commands wich contains input + mouse postion + fields that allow you to for example specify operation type like interact, consume etc. Server respond each tick with snapshot of zone you are around your aoi with all possible data with delta comporession so you get only new information. Wich approach is prefered, on wich it depends? Does they have some serious perfomance gains when you stick to one of them? Or its just matter of architecture your team prefer?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
Is there official app or something that allow you watch lectures offline?
Is there official app or something that allow you watch lectures offline?
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
What is more capable of m2 c# server or cpp from episode 4?
Hello, 1 . What is more capable of m2 c# server or cpp from episode 4? Would it make sense to use cpp version of server with c# unity client?Is it better to keep c# integration inside unity engine or create bindings to cpp client and only call bindings from c# unity?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
메모리 풀 질문있습니다.
우선 좋은강의 만들어주셔서 감사합니다.제가 질문드릴건 메모리풀을 1024까지는 32바이트단위로 만드는데, 그러면 32바이트전용 풀 64바이트 전용 풀 이렇게 만들어질거고근데 이제 요청하는데 16바이트 요청을 1000번하면,32바이트 풀안에 메모리헤더 큐가 1000개가 생기는거죠?? 해제안했다는 가정하에
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
메모리 풀 질문있습니다.
우선 좋은강의 만들어주셔서 감사합니다.제가 질문드릴건 메모리풀을 1024까지는 32바이트단위로 만드는데, 그러면 32바이트전용 풀 64바이트 전용 풀 이렇게 만들어질거고근데 이제 요청하는데 16바이트 요청을 1000번하면,32바이트 풀안에 메모리헤더 큐가 1000개가 생기는거죠?? 해제안했다는 가정하에
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
JobQueue의 Push Execute쪽 코드 질문
해결 ++아래 질문 내용을 글로벌 큐에서 추가로 처리해 주는 거였습니다.삭제가 안되서 최상단에 남깁니다.이것저것 건들면서 연습하다 보니 제 환경에서 글로벌 큐 호출을 안해서 문제였습니다. 안녕하세요?루키스님 강의를 참고하여 더미 프로젝트 하는 중에 문제가 식별 되어제가 분석한게 맞다면 강의 코드에 문제가 있어 제보 드려봅니다.문제라고 생각되는 부분은 JobQueue 클래스인데요, 문제 상황은부하가 있는 상황에서 '워커스레드를 2개 이상 돌릴 때, Execute()함수가 실행되지 않는'점을 확인하였습니다.jobCount 관련 변수의 조건이 어디서 안 맞는 것 같아서 생각해보건데,아래와 같은 경우라고 생각됩니다.// JobQueue.cpp void JobQueue::Execute() { ... if (_jobCount.fetch_sub(jobCount) == jobCount) { // 여기서 다른 워커 스레드의 _jobCount.fetch_add 발생?! LCurrentJobQueue = nullptr; return; } ... } } 그렇기 때문의 이후의 잡들이 처리되지 못하고 해당 부분에서 prevCount가 계속 쌓이고 있었습니다.// JobQueue.cpp void JobQueue::Push(JobRef job, bool pushOnly) { const int32 prevCount = _jobCount.fetch_add(1); _jobs.Push(job); // WRITE_LOCK // 여기서 prevCount가 계속 쌓여 0이 아님 if (prevCount == 0) { //그러므로 이 부분의 Excute()도 실행되지 않음 ... } 아래는 해당 클래스 cpp 전문입니다.귀한 시간 내시어 확인해주시면 감사하겠습니다!#include "pch.h" #include "JobQueue.h" #include "GlobalQueue.h" /*-------------- JobQueue ---------------*/ void JobQueue::Push(JobRef job, bool pushOnly) { const int32 prevCount = _jobCount.fetch_add(1); _jobs.Push(job); // WRITE_LOCK // 첫번째 Job을 넣은 쓰레드가 실행까지 담당 if (prevCount == 0) { // 이미 실행중인 JobQueue가 없으면 실행 if (LCurrentJobQueue == nullptr && pushOnly == false) { Execute(); } else { // 여유 있는 다른 쓰레드가 실행하도록 GlobalQueue에 넘긴다 GGlobalQueue->Push(shared_from_this()); } } } // 1) 일감이 너~무 몰리면? void JobQueue::Execute() { LCurrentJobQueue = this; while (true) { vector<JobRef> jobs; _jobs.PopAll(OUT jobs); const int32 jobCount = static_cast<int32>(jobs.size()); for (int32 i = 0; i < jobCount; i++) jobs[i]->Execute(); // 남은 일감이 0개라면 종료 if (_jobCount.fetch_sub(jobCount) == jobCount) { LCurrentJobQueue = nullptr; return; } const uint64 now = ::GetTickCount64(); if (now >= LEndTickCount) { LCurrentJobQueue = nullptr; // 여유 있는 다른 쓰레드가 실행하도록 GlobalQueue에 넘긴다 GGlobalQueue->Push(shared_from_this()); break; } } }
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
JobQueue의 Push Execute쪽 코드에 문제가 있는 것 같아 말씀 드려봅니다
안녕하세요? 루키스님 강의를 참고하여 더미 프로젝트 하는 중에 문제가 식별 되어제가 분석한게 맞다면 강의 코드에 문제가 있어 제보 드려봅니다.문제라고 생각되는 부분은 JobQueue 클래스인데요, 문제 상황은'워커스레드를 2개 이상 돌릴 때, Execute()함수가 실행되지 않는'점을 확인하였습니다.jobCount 관련 변수의 조건이 어디서 안 맞는 것 같아서 생각해보건데,아래와 같은 경우라고 생각됩니다.// JobQueue.cpp void JobQueue::Execute() { ... if (_jobCount.fetch_sub(jobCount) == jobCount) { // 여기서 다른 워커 스레드의 _jobCount.fetch_add 발생?! LCurrentJobQueue = nullptr; return; } ... } } 그렇기 때문의 이후의 잡들이 처리되지 못하고 해당 부분에서 prevCount가 계속 쌓이고 있었습니다.// JobQueue.cpp void JobQueue::Push(JobRef job, bool pushOnly) { const int32 prevCount = _jobCount.fetch_add(1); _jobs.Push(job); // WRITE_LOCK // 여기서 prevCount가 계속 쌓여 0이 아님 if (prevCount == 0) { //그러므로 이 부분의 Excute()도 실행되지 않음 ... } 아래는 해당 클래스 cpp 전문입니다.귀한 시간 내시어 확인해주시면 감사하겠습니다!#include "pch.h" #include "JobQueue.h" #include "GlobalQueue.h" /*-------------- JobQueue ---------------*/ void JobQueue::Push(JobRef job, bool pushOnly) { const int32 prevCount = _jobCount.fetch_add(1); _jobs.Push(job); // WRITE_LOCK // 첫번째 Job을 넣은 쓰레드가 실행까지 담당 if (prevCount == 0) { // 이미 실행중인 JobQueue가 없으면 실행 if (LCurrentJobQueue == nullptr && pushOnly == false) { Execute(); } else { // 여유 있는 다른 쓰레드가 실행하도록 GlobalQueue에 넘긴다 GGlobalQueue->Push(shared_from_this()); } } } // 1) 일감이 너~무 몰리면? void JobQueue::Execute() { LCurrentJobQueue = this; while (true) { vector<JobRef> jobs; _jobs.PopAll(OUT jobs); const int32 jobCount = static_cast<int32>(jobs.size()); for (int32 i = 0; i < jobCount; i++) jobs[i]->Execute(); // 남은 일감이 0개라면 종료 if (_jobCount.fetch_sub(jobCount) == jobCount) { LCurrentJobQueue = nullptr; return; } const uint64 now = ::GetTickCount64(); if (now >= LEndTickCount) { LCurrentJobQueue = nullptr; // 여유 있는 다른 쓰레드가 실행하도록 GlobalQueue에 넘긴다 GGlobalQueue->Push(shared_from_this()); break; } } }
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Protobuff is it sufficient for mmorpg?
I mean that protobuff need serialization, and its not zero copy so it introduce latency to communication. Is it suitable for game servers with 1-5k players? Or its better to use instead https://flatbuffers.dev/quick_start/ ?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
void IocpEvent::Init() is correct?
void IocpEvent::Init(){OVERLAPPED::hEvent = 0;(...)} Isnt this a mistake? hEvent isnt static field and when compiled with gcc its error: 'hEvent' is not a static member of 'OVERLAPPED'. With msvc its compiled but its interpreted as 2 different instruction wich could lead to unexpected behaviour?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
DBSynchronizer에서의 XML과 DB 동기화 문제
안녕하세요. DB관련 작업중에 이런 문제가 생겨서 어떻게 이런 결과가 생긴 것 인지 궁금해 질문 올려봅니다. 우선 모든 강의를 다 들었다는 전제하에,다음과 같은 XML 코드는 잘 동작합니다.이 코드를 기반으로간단한 로그인 시스템을 만들어 보려고Account Table과 Register Procedure을 만들었는데요문제는 기존에 있는 DB를 가져와서 DBSynchronizer의 Synchronize를 실행하는 부분에Gather 시리즈에 문제가 있습니다.Gather 시리즈를 간략하게 요약하자면, 현재 system에 있는 Table, Column, Procedures들을 모두 긁어서 While(...fetch()) 문으로 DBModel::Table, DBModel::Column등으로 매핑하는 작업입니다.여기서 Fetch할때마다 함수 가장위에 정의해둔 여러 변수들이 갱신되는데요bool값이나 숫자값은 값을 Fetch()가 값을 덮어씌워 별 문제가 없는데 tableName이나 columnName같은 특정 문자열 배열인 경우에 문제가 생겼습니다.위의 사진의 경우 columnName을 순서대로 파싱할경우각 DBModel::Column 별로 name이 accountId, email, pwHash가 되야할게accountId, emailntId, pwHashtId가 되더라구요 그래도 운이좋게끝에 tId가 공통됨으로, WChar 부분이 Fetch()시 완전히 초기화되지 않고 앞의 주소값만 넘어가서 len만큼 채우는것으로 결국 len뒤의 값은 남아 그대로 반영이 된것으로 확인 됬습니다. 각 Loop가 끝날때마다 WChar과 Vector 같은 주소값을 가지는 모든값의 초기화를 이런식으로 명시함으로써 해결할 수 있었지만, 예제코드는 잘 동작했던것을 보아하니 뭔가 코드를 빠뜨렸나 싶었습니다. 참고로 예제 코드의 Gold같은 경우name이 id, gold, name, createDate로 작은값부터 커지기 때문에 위의 문제가 발생하지 않았나 싶기도 합니다. 혹시 이 문제 저만 그런가요?원본 코드에서 spRegister의 out Parameter를 처리하기 위해 살짝 바꾸긴 했는데그거 때문이려나요
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
chrono, thread헤더가 더 필요한것 같아 질문드립니다.
GameServer.cpp에서this_thread::sleep_for(10ms); 이 코드를 위해 chrono 헤더가main 함수에 thread를 위해 thread헤더가 필요한것 같습니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
포폴 관련해서 질문드립니다.
바보같은 질문처럼 느껴지실수도 있겠지만... 게임 서버를 수강 후 배운 코드를 바탕으로 여러가지 컨텐츠를 붙여서 포폴을 만들면 좋지 못하나요? 배운 코드를 바탕으로 반드시 제 방식으로 바꿔야만 하나요? 바꿔야 한다면 어느정도로 바꿔야 할까요. 취업 준비가 너무 어렵습니다. 후배의 방황을 한번만 잡아주시면 감사드리겠습니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
DB에 배열을 추가하고 싶은데 어떻게 하면 되나요
아이템 보유 정보를 DB에 배열에 넣어서 관리하고 싶은데 지금 ORM에는 배열을 추가하는 기능은 없는 것 같습니다. 방법이 없을까요
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Macro functions - still relevant in 2025?
Hey,I wanted to ask if in 2025 will you still use macro, or replace them with new syntax eq inline functions / consts / constexpr ?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
ReaderWriterLock 부분 질문입니다.
void Lock::WriteLock()부분에서 제가 실수로 expected = EMPTY_FLAG;이 부분을 while(true) 밖에 선언했습니다.CAS과정에서 expected가 갱신되는 것을 깜빡하구요. 그럤더니, 당연히 크래시가 났는데 저는 expected가 다른 ReadLock이나 WrtieLock으로 잘못된 값으로 갱신되면 EMPTY_FLAG랑 비교하는 CAS과정을 통과할 수 없게 되어 yield를 반복하다가 TIME_OUT 크래시가 날줄 알았습니다. 그런데 ReadUnlock쪽에서 Multiple Unlock 크래시가 뜨더군요.행여나 쌍을 맞춰주지 않았을까, 코드까지 다운로드해서 비교헀더니 딱 저 부분만 수정하니 잘 동작해서왜 Multiple Unlock이 나타나는지 의문입니다. 아무래도 RAII 객체의 LockGuard부분에서 소멸자를 호출하는과정에서 Multiple_Unlock이 뜨는 것 같은데, TIMEOUT -> 스택 풀기 과정에서 (소멸자 호출)로 Multiple_Unlock이 뜨기에는 10초의 시간이 있음에도 실행하자마자 바로 크래시가 나서, 어느 부분에서 ReadUnlock까지 가는지를 모르겠습니다. 아무리 생각해도 READ_LOCK에서 lock을 잡지 못하면, Unlock까지 도달할 일이 없지 않나요?디버깅을 찍어봐도 어디서 Unlock에 도달하지는지 모르겠습니다 디버깅 정보 올립니다. 혹시 이럴때 CRASH를 낸 주체를 정확히 모르겠으면 어떤식으로 디버깅 하면서 풀어나가면 좋을까요?ChatGPT는 어디가 어떻게 에러를 내는지 명쾌한 해답을 못주네요
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Job 내부 Execute에서 Lock을 잡지 않는 이유에 대해서
안녕하세요. 양질의 강의 감사합니다. 다름이 아니라, Room Job내부 Execute를 구현하실때 Enter, Leave, BroadCast가 _players에 대한 락을 잡지 않는데, 이것은, main스레드에서 혼자 Flush함수를 실행하기 때문에 어차피 경합이 없어서 인가요? 만약 일감을 처리하려는 스레드가2개 이상일때부터는, 이런 공유데이터에 대해 작업을 하려는 경우 Execute 내부에서도 락을 잡도록 구현하게 될까요? 혹시, 이렇게 n개 이상의 Flush를 하려는 구조에서, Lock을 잡는게 맞다면, Lock때문에 자신의 Execute가 더이상 진행되지 않을때, 그 락을 잡은 스레드에게, 자신의 Job을 던져버리고, 다른 일감을 찾으러 가는 구조도 구현되게 될까요?