묻고 답해요
150만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
순위 정보를
불러오고 있어요
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
싱글코어일때 멀티 스레드 작업시 문제
노트북 환경이 싱글코어라 궁금해서 멀티스레드 환경으로 코드를 돌리니까 값이 매번 다르게 나오는데싱글코어 환경에서는 멀티스레드 테스트가 불가능 한건가요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
스마트 포인터부분에서 궁금한게 있습니다.
클래스 객체 내부에 shared_ptr가 있을 때, 객체가 소멸되면 shared_ptr이 가리키는 값은 nullptr로 자동으로 변경되서, shared_ptr가 가리키는 refCount가 자동으로 줄어드는건가요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
강의에서 이해가 안되는 부분이 있습니다.
#include "pch.h" #include "AccountManager.h" #include "PlayerManager.h" AccountManager GAccountManager; void AccountManager::AccountThenPlayer() { WRITE_LOCK; //GPlayerManager.Lock(); } void AccountManager::Lock() { WRITE_LOCK; } #include "pch.h" #include "PlayerManager.h" #include "AccountManager.h" PlayerManager GPlayerManager; void PlayerManager::PlayerThenAccount() { WRITE_LOCK; //GAccountManager.Lock(); } void PlayerManager::Lock() { WRITE_LOCK; } int main() { for (int32 i = 0; i < 1; ++i) { GThreadManager->Launch([=] { while (true) { cout << "PlayerThenAccount" << endl; GPlayerManager.PlayerThenAccount(); this_thread::sleep_for(100ms); } }); } for (int32 i = 0; i < 1; ++i) { GThreadManager->Launch([=] { while (true) { cout << "AccountThenPlayer" << endl; GAccountManager.AccountThenPlayer(); this_thread::sleep_for(100ms); } }); } GThreadManager->Join(); return 0; }위에처럼 AccountManager에서 PlayerManager의 lock을 잡는 코드를 주석처리하였고 반대도 마찬가지로 주석처리 하였는대도, debug모드시 deadLock으로 처리가 되는데, 원래 이렇게 떠야하는게 맞는건가요? 이거는 데드락 상황이 아니지 않나요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
오늘 강의중에서 이해가 안되는 부분이 있습니다.
//잡고 있는 락이 있다면 if (_lockStack.empty() == false) { // 기존에 발견되지 않은 케이스라면 데드락 다시 확인 const int32 prevId = _lockStack.top(); if (lockId != prevId) { // 재귀호출은 deadLock이 아님 싸이클 확인할 필요 없음 set<int32>& history = _lockHistory[prevId]; if (history.find(lockId) == history.end()) { history.insert(lockId); CheckCycle(); } } }위의 코드는 쓰레드 1이 lock a를 먼저 잡고 쓰레드 2가 lock b를 잡으면 a의 history에 b가 들어가게 되지않나요? 제가 생각한 history는 쓰레드 1이 lock a를 잡은상태에서 lock b까지 잡으려고 할 때 a의 history에 b가 들어간다고 이해하고 있었는데, 제가 어떤걸 놓치고 있는지 잘 모르겠습니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
수업 코드에서 Debug에선 동작하지만 Release 모드에서는 동작하지 않습니다.
올려주신 섹션 2. 멀티쓰레드 프로그래밍 Reader-Writer Lock 수업 자료를 다운 받고 실행 해보니 Debug 모드에서는 잘 동작했습니다. 하지만 Release 모드에서는 실행이 안되던데 방법이 없을까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
안녕하세요. 이직 질문이 있어 드립니다.
안녕하세요. 루키스님 강의듣고 열심히 배우고 있는 현직자 입니다.회사에서는 묻기가 그래서.. 선생님이신 루키스님께 여쭤보고 싶어요. 경력 3년 정도 되는 서버 개발자인데,이직 경험이 없어서.. 루키스님 강의 보면서 배운 내용을 토대로 포트폴리오로서버 프로젝트를 만들어야 할 지 의문입니다. 누구는 경력기술서만 작성해도 된다고 하고, 누구는 포트폴리오를 신입때처럼 만들어야 한다고 하더군요..언젠가 이직을 할 수도 있으니 미리 준비하고 싶어 루키스님 의견을 듣고 싶습니다.감사합니다!
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
수업중 궁금한 점이 있어서 질문드립니다.
#include "pch.h" #include <thread> #include <atomic> #include <mutex> #include <windows.h> mutex m; queue<int32> q; HANDLE handle; void Producer() { while (true) { { unique_lock<mutex> lock(m); q.push(100); } ::SetEvent(handle); std::this_thread::sleep_for(100ms); } } void Consumer() { while (true) { ::WaitForSingleObject(handle, INFINITE); ::ResetEvent(handle); unique_lock<mutex> lock(m); if (!q.empty()) { int32 data = q.front(); q.pop(); cout << data << endl; } } } int main() { handle = ::CreateEvent(NULL, TRUE, FALSE, NULL); std::thread t1(Producer); std::thread t2(Consumer); t1.join(); t2.join(); ::CloseHandle(handle); return 0; }에서 WaitForSingleObject이후에 signal이 auto가 아니라면 ResetEvent를 따로 적어주어야 한다 하셨는데, ResetEvent가 호출되기 전에 다른 쓰레드에 있는 SetEvent가 호출되면 어떻게 되는건가요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
IOCP 워커 스레드 순서 보장 질문 드립니다.
루키스님 안녕하세요?C#서버 강에서 넘어와서 C++서버 공부하고 있습니다. C# 서버와 비교하면서 공부하다 워커 스레드 순서 보장이 궁금해서 질문 드리게 되었습니다. C# 서버에서는 Room.Flush()따위를 메인 함수의 와일루프에서 호출해서 단일 스레드로 처리하기 때문에 순서보장이 되는 것을 직관적으로 이해했습니다. 여기 예시에서는 워커스레드를 5개를 배분해주셨습니다. C# GameRoom으로 빗대면, 긴~~ 작업 Job A와, 짧은 B가 있는데 A->B 순서로 진행이 되어야 한다고 하면, 1번 워커 스레드는 먼저 들어온 A를 처리중..2번 워커 스레드가 이어서 들어온 B 작업을 처리.. A보다 먼저 처리 완료.1번 워커 스레드가 처리중인 A 처리 완료..이렇게 B->A 순서로 처리가 될 것 같다는 생각이 들었습니다. Q1. IOCP 워커 스레드가 순서 보장이 되는지?Q2. 그럼에도 불구하고 워커스레드를 N개 하신 이유가 있을 것 같은데 C#도 그렇게 할 수 있을지? 예를 들어 Room의 처리를 1, 2, 3, 4, 5번 스레드를 파서 동시에 처리 할 수 있을지?Q3. C# 서버에서는 Room에 1개의 스레드를 배분한 특별한 이유가 있는지?궁금합니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
.
.
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
워커스레드가 1개일 때 가장 빠를 수 있을까요?
루키스님 안녕하세요?C# 서버에서 넘어와서 CPP 서버 공부하고 있습니다. 스트레스 관련해서 이해가 안되는 부분이 있어 질문 드리게 되었습니다. 제가 스트레스 테스트를 한 방법은 recvCount, sendCount 변수에 ++하여 1초에 1번 출력하는 방식으로, '개략적으로' 카운트가 되는지 테스트하고 있습니다.C# 서버에선 C_Move패킷을 각 클라이언트가 0.25초마다 서버로 보내서 100명의 더미클라이언트로 치면 서버에서 400번 Recv, 40000 Send(브로드캐스트이므로) 정도로,300명 정도까지 Move 패킷을 처리할 수 있는 수준으로 부하테스트가 되었습니다. 근데 CPP IOCP 서버에서 워커 스레드는 컴퓨터 스레드 개수에 맞게 하는게 적당하다고 하셨고, 실제 배포하신 자료에도 워커스레드는 5개를 정해주셨습니다 (저는 핵사 코어 컴퓨터를 사용 중입니다) C#과 마찬가지로 더미 클라이언트.가 C_Move 패킷을 보내고 count 변수에 ++하면서 보고 있는데, 워커 스레드가 오히려 1개일 때 월등히 작업이 빠릅니다. 스레드 1개는 300명 내외까지 가능하지만, 2개 이상부터는 100명도 버거운 수준이었습니다. 룸이 하나인 상황이어서 컨텍스트 스위칭 때문에 오히려 워커 스레드 2개부터 느릴 수 있는걸까요? 고민해봤는데 명확한 답이 안나와 질문 드립니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
MemoryPool Pop 락여부
아래 박스 쳐진 코드 부분에서 header 부분은 생성하는 부분입니다. 생성자를 호출한다는 것은 "메모리쓰기"를 한다는 것인데 멀티쓰레드 환경에서 락을 걸어야 하는 것 아닌가요?제가 정확하게 몰라서 이렇게 질문 남깁니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
안녕하세요. CV Producer() 내부의 lock 스코프 안에서 cv.notify_one()하는 것 질문드립니다.
CV Producer() 내부의 lock 스코프 안에서 cv.notify_one()하는 것 질문드립니다.그 안에서 notify_one()을 하게 되면 확실히 큐에 푸시한 후에 다른 스레드가 가로채기 전에 notify_one을 호출하니 Consumer()의 wait()에서는 확실하게 q에 값이 있는 상태가 되는 것 아닌가요? notify_one()을 한 후 Producer를 호출한 스레드는 스코프를 바로 빠져나올거고, 빠져나오면서 lock을 놓아줄 거고 그러면 놓아주는 순간 Consumer()의 wait는 누가 가로채기 전에 바로 들어오니 가짜 기상 문제가 해결되는 것 아닌가요. 아리달송합니다..
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
VS 2022 기준 ServerCore의 .lib 파일을 못찾을 수 있나요?
루키스님 안녕하세요?vs 2022에 맞춰서 IOCP 구축연습 밑바닥 부터 하고있습니다. 역시 환경 설정부터 난관이었는데요,ServerCore의 .lib파일을 GameServer가 못찾습니다 (ServerCore 빌드까지는 됩니다)강의 몇번을 돌려봐도 안되길래 좀 찾아보니까pch.h에 절대 경로를 넣어서 찾아주거나(근데 이건 아니다 싶어서)#ifdef _DEBUG #pragma comment(lib, "C:\\CppGameServer25\\CppGameServer25\\GameServer\\Libraries\\Debug\\ServerCore.lib") #else #pragma comment(lib, "Release\\ServerCore.lib") #endif강의에서 더해서 GameServer의 추가 라이브러리 디렉토리를 설정해줘야지만 .lib 파일을 찾고 GameServer가 빌드할 수 있었습니다. 일단 되니까 다행이긴 한데,됐으니까 장땡인지, 아니면 제가 경로 설정? 환경 설정?등 알아둬야 하거나 놓친 것이 있는지 조언 구하고 싶습니다.왜 강의대로만 하면 안되고 추가 라이브러리 디렉터리를 설정해줘야지만 빌드가 되는지 원리에 대해 궁금합니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
RegisterRecv()가 멀티스레드 환경에서 안전하다는 게 이해가 가지 않습니다.
안녕하세요 선생님. 선생님 강의 덕분에 요즘 서버 개발이 너무 재밌습니다. 감사합니다. 다름이 아니라 이해가 안가는 부분이 있어서 질문드립니다.1:20 초에 RegisterRecv()는 멀티스레드 환경에서 안전하다고 하셨는데 이 부분이 이해가 가지 않습니다.AcceptEx()를 걸고 나서 만약 클라이언트가 5개 붙으면 ProcessAccept()는 5번 호출될 것이고, 호출될 때마다 ProcessConnect()를 내부에서 호출하여 WSARecv()는 연결된 클라이언트마다 1번씩 호출하게 되는 것으로 코드를 이해했습니다. 그렇다면 클라이언트가 5명 붙는다면 WSARecv()는 5번 호출될텐데, 각 클라이언트가 동시에 send한다면 서버는 GetQueuedCompletionStatus()를 통과하여 동시다발적으로 ProcessRecv()를 호출할텐데 이 때 멀티스레드 critical section 문제가 발생할 것 같은데 제가 잘못 이해한 부분이 있을까요?혹시 client 별로 한 개 씩 RegisterRecv()를 등록해 놨으므로 각 client들은 각자 등록한 WSARecv()에만 연결되는 것이라서 멀티스레드 문제가 안 생긴다는 뜻일까요?
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
이동동기화 관련 질문 드립니다. 추측항법 외.
안녕하세요 루키스님. 지금은 C#서버로 칸 없이 3D 이동 동기화 토이프로젝트 여러모로 시도해보고 있습니다.제 토이 프로젝트의 목적은추측항법을 사용해 칸 없이 3D 이동 동기화로써 루키스님 강의들 Q&A 뒤적여서 이해한 추측 항법은 "목적지를 뿌려주고 거기로 어떻게 하던지간에 이동하게 해준다" 로 다음 아이디어를 적용해보게 되었습니다. 기본 아이디어는 플레이어 A가 [0,0,0]에 있다면, 바라보는 방향으로 벡터1 만큼을 더한 위치, 예를 들어 w를 누르면 [1,0,0]의 C_Move 요청 패킷을 날리고, 서버가 모든 유저들에게 브로드캐스팅 해주면,각 클라이언트는 A의 위치를 [0,0,0] 에서 [1,0,0]으로 자연스러운 Transform 변경으로 '스르륵'을 구현했습니다.// 참고용 위치 동기화 핵심 코드 void Update() { // destinationPos : S_Move패킷을 통해 갱신된 목표 위치 float distance = Vector3.Distance(transform.position, destinationPos); // 목표지점에 거의 다왔으면 목표 위치로 순간이동 if(distance < 0.1f) { transform.position = destinationPos; } else { // 스르륵 이동 transform.position = Vector3.MoveTowards(transform.position, destinationPos, Speed * Time.deltaTime); } // TODO : 보정 등 } 현재 C++ 서버도 병행해서 공부하는 저의 시점에서, 몇가지가 궁금해서 질문 드리게 되었습니다.Q1. 지금 강의, IOCP와 UE5에서 소개해주신 이동 동기화를 추측항법은 아닌 것으로 이해됩니다(과거 위치를 브로드캐스팅 해주고 있으므로). 제가 이해한게 맞을까요? Q2. 제가 구현한 아이디어와 코드도 일종의 추측항법이라고 우겨도 될까요? 포트폴리오 키워드로 녹이고 싶은 욕심이 있습니다. Q3. 제가 채택한 이동 동기화의 방법의 피드백도 가능하다면 받고 싶습니다. 위 코드에 보정은 어느 정도 넣을 예정이지만, 기본 아이디어에 대해 시니어님의 의견도 여쭈고 싶습니다. 차기 강의 항상 기대하고 있습니다 ㅎㅎ 몸은 다 나으셨는지 모르겠네요.답변 미리 감사합니다!
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
ThreadManager.h 관련 질문있습니다.
제 ThreadManager.h 소스코드입니다.이 부분과 Types.h 소스코드를 포함하여 다른 모든 코드가 강사님의 코드와 같습니다.근데 저는 이상태로 빌드하면 이러한 컴파일오류들이 발생합니다.해결방법을 찾다가 제 ThreadManager.h 소스코드부분을std::functionstd::mutexstd::vecotr<std::thread>로 바꾸면 해결이 되긴합니다.하지만 강사님의 소스코드와 같이 std를 붙이지않았을때는 왜 제 코드에선 빌드오류가 나는지 원인을 모르겠습니다.types.h에 강사님이 작성하신 using을 이용한 코드들 똑같이 작성되어있고 CorePch.h에 using namespace std; 문장또한 존재하며 CorePch.h와 Pch.h include도 빼먹지 않았습니다.. 이유를 몰라 잠이안옵니다 ㅠㅠ..
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
1:48 초에 패킷의 수 말씀하셨는데
일반적인 포트폴리오는 10~20개라이브에서는 100~200개면너무 적은 거 아닌가요? 스킬만 처리해도 되게 많은 패킷이 필요할 것 같은데일반화를 잘해서 패킷 구조 하나로도 많은 부분을 처리한다던지?.. 그런 건가요
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
35분 06초 질문 있습니다.
복사될때 RefCount가 1증가해서 넘어가기 때문에사용중에는 삭제되지 않을것이라는 보장이 있다고 말씀해주셨는대다른 쓰레드가 해당 메모리를 해제하면 삭제가 되는것 아닌가요?? 이부분이 잘이해가 안가서 질문드립니다.다시 말씀드리자면 어떻게 상호배제가 구현되는지 잘 이해가 가지 않습니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
ClientService의 Start와 Send
안녕하세요. 세션관련해서 궁금한 점이 있습니다.ClientServiceRef service를 생성해서 connect를 하는데요,이 service로 Start하는 과정이 궁금합니다. Start 함수 내부에서 sessionCount만큼 Connect를 하는데 클라이언트는 서버에 한 번만 Connect를 하면 될 텐데 maxSessionCount만큼 연결 시도하는 것은 무슨 이유인가요? 그리고 service를 생성한 후 Broadcast를 하는데 연결된 서버는 하나인데, 맥스 세션 수만큼 Broadcast를 하는 것도 이해가 안 가네요. 만약 Broadcast가 아니고 그냥 Send 함수를 구현한다면 맥스세션 수 내의 세션 중에서 어떤 세션에 Send를 호출해야 할까요?답변 부탁드립니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5: UE5 & IOCP 서버 연동
이 시리즈 25년에 계획 있으실까요?
C++도 C# Part7+Part9 처럼게임 구현하고 서버에 물리는 과정까지 하실 예정 있으신지 궁금합니다. 다른 게시글에서 나~~중에 한다고 하신걸 봤는데 25년에는 계획이 있으신가요?
주간 인기글
순위 정보를
불러오고 있어요