묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
성능 테스트 결과
SList로 구현한 코드와 Lock을 걸며 큐에 pop push를 하는 코드의 실행시간을 스레드의 수와 일의 반복수(for문의 반복횟수)를 늘려서 시간을 측정해보았더니 Lock을 걸어 실행한 시간이 더 짧게 나오는데 둘다 어쨋든 CAS연산을 해주기 때문에 그런것일까요? 그렇다고 하면 굳이 LockFree로 구현하는 이유가 뭔지 궁금합니다Lock을 쥔 스레드가 데드락이 되어 다른 스레드들도 통과를 못하는 경우가 있어서 그런건가요?
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
게임 서버 Stateful, Stateless 진로 고민
먼저 강의 재밌게 보고 있습니다. 감사합니다.이 강의를 사면서 좋아하는 게임 개발을 위해 어떤 장르든 만들 수 있는 능력을 키우는게 목표였습니다.강의를 공부하면서 진로를 생각해보니, Stateless로 취직을 하게 된다면 (예. C#을 사용하는 수집형 게임) 경력의 문제 때문에 Stateful로 갈 수 없다는 생각이 들게 되었습니다. 또한 요즘은 Stateless 공고도 많이 없어서 이쪽으로 갈 경우 나중에 경력이 망할 수도 있는게 아닌지 불안합니다. (실력이 아닌 기술 스택에 의한 경력을 안쳐준다든지...)제가 만들고 싶은 게임이 아니라도 Stateful로 경력을 시작해서 원하는 곳으로 이직을 할 기반을 만드는 것이 맞는지, 그냥 Stateless여도 이직할 곳이 꽤 있으니 원하는 회사로 지원하는게 맞는지 너무 어렵습니다.공부만 생각하고 싶은데, 집중이 안되서 질문 드립니다...
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
WaitOnAddress와 Sleep의 차이 질문
Sleep()은 현재의 타임 슬라이스를 모두 포기하고 인자로 들어온 값 만큼 스케쥴링을 포기하는 것은 맞지만 여전히 'Ready 상태'인 반면 WaitOnAddress()는 아예 'Blocked 상태'로 빠져 버려서, 스레드가 깨어나는 상황이라면 Dispatcher가 직접 Ready Queue로 스레드를 넣어줘서 Ready 상태가 됨에 따라 다시 스케쥴링이 되는 상황으로 이해했는데 올바른 방향으로 이해한 것일까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
패킷 보내는 두가지 방법 질문
// 입장 사실을 신입 플레이어에게 알린다. { Protocol::S_ENTER_GAME enterGamePkt; enterGamePkt.set_success(success); Protocol::PlayerInfo* playerInfo = new Protocol::PlayerInfo(); playerInfo->CopyFrom(*(player->playerInfo)); enterGamePkt.set_allocated_player(playerInfo); //enterGamePkt.releasse_player(); SendBufferRef sendBuffer = ServerPacketHandler::MakeSendBuffer(enterGamePkt); if (auto session = player->session.lock()) session->Send(sendBuffer); }이 부분에서 궁금한게 두가지 있습니다.1. 이부분에서 두가지 방법이라는게 이렇게 두가지가 맞나요?동적할당, 복사, set_allocated_player 이렇게 해서 sendbuffer하기or 동적할당, copy없이 그냥 player->playerInfo를 set_alloc 한 다음 sendbuffer 마치고 enterGamdPkt.release_player() 호출하기. 아래 코드처럼 정적할당된 enterGamePkt에 기본으로 있는 playerInfo를 mutable get해서 copy 하면 안되나요? 이렇게 하면 메모리는 신경안써도 될거같아서요.enterGamePkt.mutable_player()->CopyFrom(*(player->playerInfo));
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
궁금한거 있습니다.
ClientSocket 즉 Session 의 소켓을 CreateIoCompletionPort 를 이용하여 등록해주어야지만 IOCP 큐로 부터 통지가 오지않나요? WSARecv 만 걸었는데 어떻게 통지가 오는지 궁금합니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
recv 할게 없어도 무한 while문을 도는데 괜찮은건가요?
uint32 RecvWorker::Run() { while (Running) { TArray<uint8> Packet; if (ReceivePacket(OUT Packet)) { /*패킷을 큐에 등록*/ } } return 0; } bool RecvWorker::ReceivePacket(TArray<uint8>& OutPacket) { // 패킷 헤더 파싱 const int32 HeaderSize = sizeof(FPacketHeader); TArray<uint8> HeaderBuffer; HeaderBuffer.AddZeroed(HeaderSize); if (ReceiveDesireBytes(HeaderBuffer.GetData(), HeaderSize) == false) return false; /*...*/ } bool RecvWorker::ReceiveDesireBytes(uint8* Results, int32 Size) { uint32 PendingDataSize; //연결 종료되면 packetrecvsize 0으로 옴 -> 연결 끊겼으면 종료. if (Socket->HasPendingData(PendingDataSize) == false || PendingDataSize <= 0) return false; /*...*/ }recvworker 쓰레드를 만들고 run이 실행됐는데 커널의 recv버퍼에 읽을게 없을 때헤더확인을 위한 ReceiveDesireBytes 호출Socket->HasPendingdata() 에서 return falseReceiveDesireBytes 에서 return falseRun에서 ReceivePacket return false로 recv할게 올때까지 while문 무한반복이렇게 되는데 while문이 의미없이 무한반복하고 있는게 좀 걸려서 질문합니다.recv가 계속 올거라 상관이 없어서 이렇게 처리해도 큰 상관이 없는건가요?그게 아니면 혹시 Socket->Recv 에서 블로킹이 걸리게 만들어놓고 쓰레드는 대기하다가 서버로부터 읽을게 오면 알아서 블로킹이 풀리고 일을 하도록 하는건 별로인가요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
MySQL 연동
DB 연동은 어떻게하면 좋을까요 ㅜㅜ 강의에 DB에 대한 내용이 없네요
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
잡큐단위 내부에서 잡큐호출
이미 잡큐로 넘긴 일감안에서 함수호출을 일감으로 넘기는 구조에 대해서 의문이 생겼습니다( Enter를 DoAsync로 호출했는데, 내부에서 다시 room함수를 DoAsync로 호출한 상황 ) 제가 먼저 고민해본 결과는 어차피 일감으로 넘겼으니 동기로 바로 호출해서 순서도 지키고 괜찮을 것 같다.-> 다만, 동기 호출이 내부에서 반복되어 오래 걸릴경우 스레드가 잡혀있을 수 있음( 실행시간을 정해줬다 하지만 동기호출이 반복될 경우 ) 내부 함수 호출도 잡큐단위로 넘기면 GlobalQueue로 스레드 일감 분배되고 좋을 거 같다.-> 다만, 바로바로 처리하지 않을 수 있기에 순서(?) 문제가 생길 것 같다.엄청 무거운 뭐 길찾기라던지의 작업이 아닌이상 그냥 동기 호출하고, 무거운것만 다시 잡큐로 넘기는게 좋은 방법이라는 생각도 들기도 하고 그냥 에라 모르겠다 싹다 동기 or 잡큐로 넘기기 방식도 있을거 같은데 강사님의 의견이 궁금합니다.
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
JobTimer 구동 스레드
모든 스레드가 distribute하지 않고, 메인 스레드만 담당하게 해주면 락을 잡을 필요도 없지 않나요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
포트폴리오 작성 후 확장 방향에 대해 질문이 있어서 글을 남깁니다
안녕하세요저는 C# C++ 등 서버 강의를 수강해왔고 꽤 오랜 시간이 지났지만 올해 집중적으로 준비를 했습니다. 결론부터 말씀을 드리자면포트폴리오를 작성 중 향후 확장 설계에 관해 궁금한 점이 생겨서 질문 글을 남깁니다. 현재 제 PC 사양에서 로컬 테스트와 분산 환경 테스트정도 진행했습니다. 하지만 AWS나 Azure 같은 로드밸런서를 사용하지 않아서 제한된 환경이었구요 워커 분배 모델에서 Idle 상태의 시간에 따라 워커를 분배하는 방식이 다르다고 알고있습니다.게임 로직을 처리하는 워커는 상대적으로 바쁘기 때문에 코어 수만큼, IO 를 처리하는 워커는 idle 타임이 대부분이기에 코어 x 2를 배치한다라고 알고있습니다. 현재 저는 IO , Logic , Send 총 3가지의 워커를 나눠서 사용하고있고 추후 DB 등록에 대한것도 추가될 수 있다고 생각하는데요. 수평 확장으로 수백개의 Room이 돌아가게되면 busy-wait (현재 Logic 워커) Loop를 돌고 있는데 이게 cpu를 놓아주지 않는 경우가 생길 수 있을까요?이렇게 될경우 IO Stall 현상이 나타나면 Server에선 치명적으로 다가올 수 있다고 생각합니다. 그렇다면 Logic 워커에서 Sleep, 또는 OS로 CPU 제어를 명시적으로 반환을 하도록 설계를 해야할까요? 지금 하고있는 고민이 맞는지 의심스러워 질문을 남기게 됐습니다. 그리고 JobQueue (Update가 들어갈)에 IO Job이 쌓여있을경우 fixed tick 기반의 서버 프레임에 변동이 발생하는데 이걸 어떻게 해결할 수 있을까요?Timer를 통한 재귀적 등록이냐, Timer에 Push하는 전용 워커를 두고 fixed tick 마다 깨어나 전체 Room에 대한 Timer 등록이냐 너무 복잡해서 질문을 남기게 됐습니다.그리고 신입으로 상채 지원해서 서류, 과제 통과 후 면접이 잡혔는데 공채와는 사뭇 다른 면접일 것 같은데 혹시 조언은 구할 수 있을까요?여기는 플랫폼 서비스를 제공하는 C# 서버를 주로 다룬다고 해서 준비해야 할 개념적인 부분이 있을까요?제가 준비하면서 고민했던 굉장히 추상적인 내용들이라 모호한 부분이 많습니다.항상 좋은 강의를 남겨주셔서 감사합니다. 시간이 지나도 계속 찾아보게 만드는 강의여서 갑자기 찾아와 질문을 남기게 됐습니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
TryPop() 동작 관련 질문
0이 아닌 -countIncrease와 비교하는 이유가 다른 쓰레드들에 의해 internalCount가 이미 음수가 되어있는 경우 countIncrease의 증가로 인해 정확히 0이 되는 상황일때, 삭제 할 수 있도록 처리하기 위함이 맞나요? compare_exchange_strong에 의해서 oldHead가 최신 _head로 갱신되므로, 이미 pop된 객체에 대해 다시 접근한다거나, 쓰레드가 함수의 무한 루프에 빠지는 경우가 배제되는 것으로 이해했는데 맞을까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
로드맵 C#서버 C++서버 방향성 질문
안녕하세요 강사닙 C++ IOCP강의 정말 감탄하면서 잘 들었습니다. ( 되새김질 50번은 한거같네요 ) 양질의 강의 제공해주신 점 정말 감사합니다.현재 저는 대학교 3학년 복학 준비중이고, 졸업작품 제작을 염두에 두고 있는 상태입니다.로드맵 관련해서 질문하고 싶은게 있습니다. Unity의 part4 C#목차를 보면 C++서버와 동일하더라고요.근데 굳이 후순위에 배치하신점이 궁금합니다.( C++서버와 구조가 같아보이는데 들어야할까요? ) ( JobQueue같은 스레드 배치항목만 이해했다면 굳이? 싶어서요 ) 또한 unity시리즈의 데베쪽 강의와 연동쪽 (part 5~9 )를 듣고 싶은데, unity엔진에 대한 경험이 없어도 될까요?UE로 포폴을 작성할 생각인데, C++연동 강의를 듣고 UE공부를 할려고 합니다. (GAS 등 ) 이 때, 공부 순서를 어떻게 해야할지 감이 안잡혀서요...C#으로 데베연동쪽으로 컨텐츠 구현감을 잡고나서 하는게 좋을까요?분산서버의 경우 C#과 C++을 혼용해서 개발할 수 있을거 같은데, 이걸 위해서라도 C#을 공부하는게 좋을까요? ( 인증서버는 C#으로 구현하는 경우가 많으니 )
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
스레드 id를 출력할떄 메인스레드 id도 출력되나요?
메인스레드가 1번을 먹는것까지는 이해했는데 그 이후에 원래 1부터 6까지 전부 출력되는것이 맞나요? 루키스님 화면에서는 2에서 6까지만 출력이 되는걸로 보여서 질문드립니다 해결했습니다 감사합니다
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
생명주기를 위한 의도적 복사
안녕하세요 강의 정말 감탄하면서 잘 수강하고 있습니다. Job에서 보편참조로 받았는데 forward로 하지 않은 것은 Ref들의 생명연장을 해주기 위해 의도적으로 복사하기 위한 의도일까요?JobSerializer로 인터페이스를 제공한 쪽에서는 어차피 Job내부에서 복사를 일으키고 있으니 forwad로 전달하는 의도가 맞을까요?강의 코드를 매일 복기하면서 보고 있는데 정말 감탄이 나오네요 항상 감사드립니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
락프리의 실무에서 사용 질문
락프리 구조를 사용하지않는다고 하셨는데 락프리를 써야 서버의 성능이 제대로 나오는것 아닌가요? 오히려 너무 어려워서 제대로 만든것이 아니라면 서버가 죽거나 오류가 날수 있기때문에 안쓰는 건가요?락을 사용해서 데이터 하나에 접근을하면 싱글 스레드보다 성능이 낮을것같아서 질문드려요멀티스레드를 사용하는 경우가 실무에선 많이 없을까요? 아니면 boost.asio에 있는 lockfree자료구조를 사용하나요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
에러코드
Spawn 수업을 진행 하던 도중에 , 클라이언트 빌드 이후에 발생한 에러인데 어느부분에서 발생하는지 몰라서 에러코드를 남겨봅니다.. 자동화 이후 빌드까진 다되었었는데 발생했습니다. 캐시파일들같은 파일들을 다 삭제하고 리빌드를 해도 동일한 오류가 발생합니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
32bit threadID와 16비트 상위 WriteFlag에 대해
32비트짜리 threadID를 비트 연산으로 16비트 옮겨준뒤 짤라준 것을 WriteFlag에 담는 과정에서 손실이 일어나는거 아닌가요? 그래서 현재 ThreadID와 _lockFlag의 WriteFlag를 다시 16비트 옮겨준 값이랑 비교했을 때 일치하지 않는 문제가 발생할 수 있지 않나요? 강의 18:40초입니다. ( ThreadID를 16비트로 관리하지 않는 이유는 또 무엇인가요??? )
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
언리얼 버전
안녕하세요 항상 수준높은 강의해주셔서 감사합니다강의에선 5.3언리얼 버전으로 진행하는데, 최신버전인 5.6 버전으로 진행해도 무방할까요?
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
mutex와 sleep 차이점
mutex도 커널로 sleep가 되는걸로 알고 있는데 스핀락을 구현하면서 sleep를 같이 구현하는것과 mutex를 사용하는것의 차이가 궁금합니다
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
ProtoBuf UE 연동 문제
Spawn #2 따라하고 실행해보는데 메모리 충돌로 인해 언리얼 크래쉬가 발생하네요혼자 열심히 시도해 본 결과 UE FMemeory와 ProtoBuf 소멸자에서 delete 되는 부분에서 UE delete 오버라이드 문제인 것 까진 알게 되었으나 어떻게 해결해야 할 지 모르겠어서 질문 드립니다UE 5.6 버전이고, ProtoBuf는 C++ 5.29.5(29.5) 버전입니다vcpkg를 사용해서 라이브러리 다운 받았고 /MD 동적 라이브러리로 UE 프로젝트에 포함시켰습니다 (dll로 인해서 new/delete 오버라이드로 인한 메모리 충돌 문제가 더 쉽게 발생하여 /MT로 포함하는 것이 나을 수도 있겠다고 LLM(gpt, grok) 등이 말한 내용을 적용하고자 하였으나 빌드를 실패하여 그 부분은 진행하지 못하였습니다)다음 이미지는 실행했을 때 크래쉬가 발생하는 부분과 로그 일부 입니다LoginId:468bde9140a0ef5bd78746b7d5b86a2cEpicAccountId:e6607fa7037e41448797c486f54e5315Unhandled Exception: EXCEPTION_ACCESS_VIOLATION reading address 0x0000023d9d00116fUnrealEditor_CoreUnrealEditor_CoreUnrealEditor_S1!operator delete() [C:\Program Files\Epic Games\UE_5.6\Engine\Source\Runtime\Core\Public\HAL\PerModuleInline.inl:9]UnrealEditor_S1!Protocol::PlayerInfo::`scalar deleting destructor'()libprotobuf!google::protobuf::internal::RepeatedPtrFieldBase::DestroyProtos() [C:\Users\yudle\vcpkg\buildtrees\protobuf\src\v5.29.5-5bafd96eab.clean\src\google\protobuf\repeated_ptr_field.cc:90]UnrealEditor_S1!Protocol::S_LOGIN::~S_LOGIN() [D:\GitHub\S1\Source\S1\Network\Protocol.pb.cc:586]UnrealEditor_S1!std::_Func_impl_no_allocServerPacketHandler::Init'::2'::<lambda_1>,bool,TSharedPtr<PacketSession,1> &,unsigned char *,int>::_Do_call() [C:\Program Files\Microsoft Visual Studio\2022\Community\VC\Tools\MSVC\14.38.33130\INCLUDE\functional:810]UnrealEditor_S1!PacketSession::HandleRecvPackets() [D:\GitHub\S1\Source\S1\Network\PacketSession.cpp:37]UnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_CoreUObjectUnrealEditor_EngineUnrealEditor_EngineUnrealEditor_EngineUnrealEditor_EngineUnrealEditor_EngineUnrealEditor_CoreUnrealEditor_CoreUnrealEditor_CoreUnrealEditor_CoreUnrealEditor_EngineUnrealEditor_EngineUnrealEditor_EngineUnrealEditor_EngineUnrealEditor_UnrealEdUnrealEditor_UnrealEdUnrealEditorUnrealEditorUnrealEditorUnrealEditorUnrealEditorUnrealEditorkernel32ntdllS_LOGIN 패킷의 소멸자에서 오염된 메모리 접근 문제로 크래시가 발생한 것으로 보입니다