묻고 답해요
141만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
서버 연동 질문드립니다
벌써 루키스님 강의를 보기 시작한지 2년이 넘었습니다.항상 좋은 강의 감사드립니다 특히 요즘 다이렉트 강의보면서 혼자 공부할 때는 많이 힘들었는데 엔진 구조 개발 부분에서 많이 얻어가고 있습니다.이 강의를 공개하신 시점도 벌써 2년이 지나게 되었는데 혹시 언리얼과 게임서버 연동 하실 때 이 서버를 그대로 사용 하실 것 인지 아니면 다른 방식으로 업그레이드 후 서버 개발 후 연동하실지가 궁금합니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
내장 SQL Server
SQL Server 2022에서는 SQL Server Native Client 드라이버가 제거된 것 같습니다. 이 경우에는 ODBC Driver 17 for SQL Server 드라이버를 활용하면 되나요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
수업자료 다운로드 후 빌드 오류
첨부파일을 다운받아 그대로 빌드를 실행했는데, 다음의 부분에서 에러가 생깁니다.#if 3017001 < PROTOBUF_MIN_PROTOC_VERSION #error This file was generated by an older version of protoc which is #error incompatible with your Protocol Buffer headers. Please #error regenerate this file with a newer version of protoc. #endif이상한 점이 protoc 3.17.1 버전으로 생성한 Enum.pb.h인데 PROTOBUF_MIN_PROTOC_VERSION의 값이 3021000으로 뜹니다. 혹시 Visual studio 2022를 사용해서 ide때문에 에러가 생기는 것일까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
의사코드 질문입니다.
while 루프 내부에서 expected = false 를 굳이 왜 해야하는 질문이 들었는데요.의사코드를 보면 else 구문에서 expected = locked에 때문에 한다고 말씀해주셨는데결국 if문에서 _locked=true일 때 조건을 만족하는 경우가 생겨서 그런건가요? false로 조건을 통과해야되는 데 말이죠. (잠겼는데 통과하는 경우가 발생) 그렇다면 의사코드에서 else 구문에서 expected = _locked을 왜하는지 의문이 드는데, "그냥 칩회사에서 그렇게 구현했다." 라고 받아들이면 되는건가요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
IOCP 관련 질문이 있습니다.
이제 개발을 할때 WSASend함수를 통해 Scatter-Gether 방식으로 전달을 한다고 하면 내부적으로는 해당 데이터들이 하나의 Sendbuffe에 담겨서 가는지가 궁금합니다.WSASend에 요청한 데이터가 너무 커서 2번이상의 걸처 나눠서 전송이 된다면, 모든 데이터가 전송이 완료되어야지만 IOCP GQCS에서 완료되었다는 사실을 알 수 있는지 궁금합니다. 정리)1. Scatter-Gether를 통해서 여러 데이터를 보내면 내부적으로 1개의 Send Buffer에 담아서 보내지는지2.WSASend 호출 -> 데이터가 너무 커서 2개로 짤림이때 1개의 데이터를 전송 완료 후 GQCS OR2개의 데이터를 전부 전송 완료 후 GQCS에 등록 이 되는지 궁금합니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
DisconnectEx
해당함수를 사용하면 기존에 생성했던 Socket을 다시 만들필요 없이 재사용할 수 있다라고 설명하셨는데, 해당 코드를 보면 Disconnect가 될 시 Service에서 Session을제거하기 때문에 해당 Session은 메모리에서 해제가 되는것으로 알고 있습니다. 그럼 다시 CreateSocket함수를 통해서 socket이 생성되면 사실 의미가 없는게 아닌가 궁금합니다. 그냥 SocketPool을 만들어서 제가될떄 넣고, 생성될때 꺼내쓰는게 효율적일 것 같은데 혹시 어떻게 생각하시는지 궁금합니다.
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
게임 설명란의 포폴이요
혹시 강의 설명란에 나와있는 mmorpg 3d 게임 포폴을 완성하려면 어디까지 들어야 하나요? 현재 part4까지 나와있는데 여기까지 들어도 만들 수 있는가요? 없다면 5,6 은 언제쯤 나올지 궁금합니다..
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
오브젝트 풀에서 스마트포인터를 반환하는이유
안녕하세요오브젝트 풀을 사용하는 이유가 객체의 동적할당/해제의 회수를 줄이기 위함이라 생각하는데요return std::shared_ptr<T> ptr {pop(), push};을 사용하게되면 shared_ptr 내부에서 객체를 관리하기 위한 공간이 동적으로 할당되게된다고 생각되는데요. (refcount 같은것들)그렇게되면 동적할당된 객체는 재사용이되지만 동적할당 비용을 줄이기 위함은 딱히 의미가 없어진다고 생각되는데요그럼에도 쓰는게 의미가있는가요?오히려 make_shared를 쓰는게 더 나은건 아닌지 궁금합니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
언리얼 클라와 실습 IOCP 서버를 연동
항상 좋은 강의 감사합니다!다름이 아니라, 추후에 언리얼 클라랑 서버를 연동하는 강의가 나중에 나온다고 하셨는데 혹시 언제쯤 나오는지가 궁금해서 질문드립니다!!
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
추가 질문) AcceptEx함수를 사용하지않고 WSAIoctl 사용이유
https://stackoverflow.com/questions/4470645/acceptex-without-wsaioctl다른 질문에서 보내주신 링크로 들어가서 확인 했습니다.추가적으로 제가 이해한 부분이 맞는지 확인해주시면 감사하겠습니다. 기본적으로 AcceptEX, ConnectEX 함수등은 아키텍처가 외부에 있기에 많은 비용이 발생하여 맵핑하여 사용한다고 생각이 듭니다 이것을 제외하고 추가적인 부분이 있을까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
AccountManager.h에서는 pch.h가 include되어 있는지 모르는데
정말 기초적인건데 갑자기 이해가 안돼서 질문 남깁니다.AccountManager.h에서는 pch.h가 include되어 있는지 모르고 AccountManager.cpp에만 include되어 있는데 어떻게 AccountManager에서는 map에 std::를 안붙이고 쓰고, int32 타입을 쓸 수 있는걸까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
echo server가 아닌 경우 연결 체크에 대한 질문
유저의 input이 없을 경우 보낼 데이터가 없는 간단한 채팅 서버라고 할 때, 이런 경우에 연결을 확인하기 위해 ping pong을 통해 지속적으로 연결 상태를 체크하나요?
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
데드락 관련해서 질문이 있습니다. 루키스님!
데드락 관련해서 버그가 떠서 질문글을 남깁니다.윈도우 어플리케이션을 생성해서 윈도우 메인에 서버에게 C_LOGIN을 보내는 패킷을 생성했습니다. 밑은 해당 코드입니다. bool flag = true; while (true) { if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { if (WM_QUIT == msg.message) break; if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } else { CEngine::GetInst()->progress(); CEditorObjMgr::GetInst()->progress(); ImGuiMgr::GetInst()->progress(); // 렌더 종료 CDevice::GetInst()->Present(); if (service->GetCurrentSessionCount() > 0 && KEY_RELEASE(KEY::A) && flag == true) { Protocol::C_LOGIN pkt; auto sendBuffer = ServerPacketHandler::MakeSendBuffer(pkt); sendBuffer = nullptr; flag = false; } } } return (int) msg.wParam; }A를 클릭해서 서버와 연결한 후에 X를 눌러서 윈도우 창을 닫았는데, 이후 이렇게 코어글로벌이 종료될 때, GSendBufferManager를 delete하는 부분에서 타고타고 들어가서 DeadLockProfiler가 DeadLock이 존재했다고, 알려줬습니다.Server에 OnConnected가 되었을 때, 패킷을 보내면 이런 문제가 일어나지 않았는데, 원하는 때, 원하는 키를 입력해서 패킷을 보내려고 하니까 문제가 일어나네요 ㅜㅜ문제를 알 수 있을까요? 프로토 버퍼를 사용해서 주고 받고 있습니다!
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
안녕하세요 루키스님. 클라 연동에 관해서 질문을 드리고 싶습니다.
안녕하세요 루키스님.제가 비쥬얼 스튜디오에서 윈도우 어플리케이션을 만들어서 DX11포폴을 만들고 서버를 연동하려고 시도중입니다. 이 상황에서 wWinMain에 ClientServiceRef service = MakeShared<ClientService>( NetAddress(L"127.0.0.1", 7777), MakeShared<IocpCore>(), MakeShared<ServerSession>, // TODO : SessionManager 등 1); ASSERT_CRASH(service->Start()); GThreadManager->SetFlags(1); for (int32 i = 0; i < 2; i++) { GThreadManager->Launch([=]() { while (true) { service->GetIocpCore()->Dispatch(10); } }); } //밑은 DX11을 작동시켜주기 위한 함수들입니다. while (true) { if (PeekMessage(&msg, nullptr, 0, 0, PM_REMOVE)) { if (WM_QUIT == msg.message) break; if (!TranslateAccelerator(msg.hwnd, hAccelTable, &msg)) { TranslateMessage(&msg); DispatchMessage(&msg); } } else { CEngine::GetInst()->progress(); CEditorObjMgr::GetInst()->progress(); ImGuiMgr::GetInst()->progress(); // 렌더 종료 CDevice::GetInst()->Present(); } }이렇게 쓰레드를 생성해서 작동을 시켜주었습니다.그런데 생성된 게임 윈도우에서 X키를 눌러서 프로그램을 강제로 종료시켰는데, 이 메인 쓰레드 자체는 정상적으로 WM_DESTROY를 호출 받아서 종료되었는데, 멀티 쓰레드들이 멈추지 않고 계속 돌아 프로그램이 종료되지 않고, 좀비처럼 살아남는 현상이 계속되고 있습니다.쓰레드를 강제로 종료시키니 메모리 릭이 남고, 어떻게 문제를 해결해야할지 해결책을 찾지 못해서 이렇게 질문 남깁니다.참고) 루키스님의 패킷 직렬화#3 코드를 참조해서 만들고 있습니다!감사합니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
비동기를 제대로 이해했는지 궁금합니다
1) 제가 제대로 비동기 방식을 이해한게 맞는지 궁금합니다. 비동기 방식이 어떤 함수를 호출한다면 함수를 지금 바로 처리하지 않고 예약같은 개념으로 요청한 함수를 나중에 처리하고 그동안 요청한 함수외에 다른 부분을 실행하는걸로 이해를 했는데 맞는건지 궁금합니다.2) 만약에 제가 이해한 방식대로 비동기가 진행이 된다면 수업에서 진행한 ::WSAWaitForMultipleEvents(1, &wsaEvent, TRUE, WSA_INFINITE, FALSE); 코드에서 블로킹 방식처럼 진행하는데 이 부분은 비동기와는 맞지 않는 부분아닌가요??
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
데드락 탐지
데드락 탐지에 관련해서 궁금한게 있어서 질문드립니다.아래의 코드로 lock_guard를 이용해서 데드락을 탐지 하려고하는데 데드락이 되는 상황이 발생하고, 탐지는 안되는 경우가 가끔 발생하네요... DeadLockProfiler는 예제의 코드를 복사해서 사용했습니다. #include "pch.h" #include <iostream> #include "DeadLockProfiler.h" mutex lock1; mutex lock2; void Test(); void Test2(); void Test() { DeadLockProfiler::GetInst()->PushLock("Test"); lock_guard<mutex> gurad(lock1); Test2(); DeadLockProfiler::GetInst()->PopLock("Test"); } void Test2() { DeadLockProfiler::GetInst()->PushLock("Test2"); lock_guard<mutex> gurad(lock2); Test(); DeadLockProfiler::GetInst()->PopLock("Test2"); } int main() { thread th1([=] { while (1) { cout << "test" << endl; Test(); this_thread::sleep_for(100ms); } }); thread th2([=] { while (1) { cout << "test2" << endl; Test2(); this_thread::sleep_for(100ms); } }); th1.join(); th2.join(); return 0; }
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
템플릿 흑마법을 보고 질문 글을 남깁니다.
Job Queue #2의 영상을 보고 질문드립니다.이 영상을 보고 저번에 메모리 관련해서도 보고 느낀 것인데, 템플릿 흑마법을 따로 공부할 수 있는 책이나 가이드가 있을까요?루키스님의 영상을 볼 때는 템플릿 흑마법이 이해가 가긴 하는데, 이걸 스스로 짤 생각을 하니 도저히 엄두가 안나서 공부가 필요할 것 같아 이렇게 질문 글을 남깁니다.
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
혹시 언리얼 클라에서는 WSA Recv가 아니라 그냥 recv 사용해야 하나요?
서버랑 언리얼 연동 후 단순한 데이터 교환은 되는데, 패킷을 받아 스폰 기능을 사용하려고 하면 IsInGameThread() 라는 에러가 뜹니다. 대충 느낌을 보아하니 뭔가 외부 쓰레드? 그런 걸 차단하는 느낌이 드는데...Dispatch 해주는 워커쓰레드한테 FRunable 해줘도 해결 되지 않아서 질문 드립니다.. 혹시 다른 사람은 어떤가 싶어, 코드를 보니 서버는 IOCP를 사용하되, 언리얼에서는 그냥 recv만 사용하더군요.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
강의에서 allocate 함수 두번 호출되는 것에 대해
강의 7:26 초 쯤에서의vector<Knight, StlAllocator<Knight> v(100);이후 allocate 함수 호출 과정에서 처음에 1, 두번째 100이 호출 되는 이유는 무엇인가요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Server Service에서 함수포인터 사용관련해서 질문을 남깁니다.
using SessionFactory = function<SessionRef(void)>; Service(ServiceType type, NetAddress address, IocpCoreRef core, SessionFactory factory, int32 maxSessionCount = 1); Service의 생성자는 이런식으로 SessionFactory라는 함수포인터를 받고 있습니다. 그런데 함수포인터를 전달하지 않고, ServerServiceRef service = MakeShared<ServerService>( NetAddress(L"127.0.0.1", 7777), MakeShared<IocpCore>(), MakeShared<GameSession>, // TODO : SessionManager 등 100); 이렇게 MakeShared로 생성된 GameSession 클래스를 전달해도 잘 동작하는데, 함수포인터 형식에 클래스를 그냥 사용해도 잘 동작하는 이유가 궁금합니다.MakeShared의 함수에서 ()를 사용하지 않으면, 내부적으로 xnew함수만 전달되어서 그런것인가요? 제가 이해한게 정확한지 모르겠어서 질문을 남깁니다. (한번도 function을 이렇게 사용한적이 없어서 모르겠네요 ㅜㅜ)