묻고 답해요
161만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[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년에는 계획이 있으신가요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
강의 다 듣고 와서 락 관련 질문드립니다.
강의 잘 들었습니다🙏락을 구현할 때 ReadLock을 만들었는데 전체 강의 코드를 보면 ReadLock을 사용하는 데가 없더라고요(DB 쪽은 스킵했습니다). 우리 프로젝트에만 해당하는 특별한 경우인지 실무에서도 WriteLock 사용이 압도적으로 높은 것인지 궁금합니다.락을 직접 구현한 이유 중 하나가 (동일 스레드 기준) 쓰기 락이 걸려있을 때 읽기를 허용하기 위한 것도 있었는데, 읽기 락을 만들어놓고 한 번도 사용하지 않았다는 사실이 약간 신기하게 느껴졌습니다.+) 답변하시기 전에 추가 질문서두에 말씀하신, 직접 락을 구현하는 이유가, 기획 데이터는 대부분 읽기를 수행하는데(잘 안 바뀌는 데이터), 굳이 스레드 간에 상호배타적일 필요가 없기 때문에(표준을 이용한 방법이 있으나), 읽기에 대해선 모든 스레드가 접근할 수 있게 ReaderLock이 필요한 걸로 이해했습니다.그렇다면 운영에서 기획 데이터에 아이템을 추가한 걸 화면에 보여줘야 할 때는, WRITE_LOCK이 사용되나요?..기획 데이터를 실시간으로 읽어오는 건지 업데이트를 하면 서버를 재시작하는 건지 궁금합니다. 실무 경험이 없다 보니까 기획 데이터로 예를 들어주실 때 상황이 명확하게 안 그려지네요. 서버를 재시작하는 거라면 이미 변경된 데이터를 서버 구동 때 읽어오는데 쓰기 락이 왜 필요한지 궁금합니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
DoGlobalQueueWork함수에 관한 질문입니다!
안녕하세요.이전 질문 중에 DoGlobalQueueWork가 실행되면서 GlobalQueue에서 일감을 꺼내 멀티스레드 환경에서 처리되는 도중에, 데이터가 겹쳐 레이스 컨디션이 발생할 수 있냐는 질문에 강사님께서 멀티스레드 이슈가 다시 생길 수도 있다고 말씀하셨습니다. 관련해서 궁금한 점이 생겼습니다.적어도 저희 강의에 적용된 코드에 국한해서, 데이터가 겹친다는 이유로 레이스 컨디션이 발생할 수 없지 않나요? GlobalQueue로 데이터를 넣고 빼는 부분에 락을 거니까 해당 부분에서는 아주 잠깐의 락 대기 시간이 생길 수 있고, 일감을 일단 Pop한 이후에는 데이터가 겹치는 일이 생길 수 없는 것 같은데, 이전 답변을 보고는 생길 수 있는 가능성이 없지 않다는 느낌을 받아서 이 궁금증을 해소하고 싶습니다~이전 질문에서 답변해주신 것 중에 Zone 단위로 JobQueue를 배치하는 경우 데이터 공유가 거의 없고 Actor 단위일 경우엔는 필연적으로 순간에 Lock을 걸거나, 정밀 조정이 어려우니까 그냥 락 걸지 않고 데이터를 get할 수 있다는 내용은 이해했습니다!
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
운영체제에 구애받지 않는 네크워크 모델
너무나 알찬 수업 잘 듣고있습니다.수업들 듣던 중, 의문이 하나 생겨서 질문남깁니다. 네트워크 라이브러리중, boost::asio 를 이용해서 운영체제에 독립적인 환경을 구축할 수 있을거 같은데,네트워크 부분은 윈도우 맞춤으로 수업하시는 이유가 궁금합니다. boost::asio 의 기능만으로는, 효율적인 게임서버를 구축하기 어려워서 인가요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
서버 컨텐츠 제작
선생님 제가 파트5를 아직 안 본 상태인데파트4 내용으로 기반을 잡은 상태에서제가 마음대로 이어서 만들면 되지만이어서 파트5에서는 언리얼과 연동하면서정석적인 컨텐츠 개발 설계를 배울 수 있는 걸까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
서버 중지 기능
안녕하세요. 서버를 중지하고자 하면 어떤 절차를 거쳐야 하나요? Listener