묻고 답해요
156만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Push의 LCurrentJobQueue관련 질문입니다.
현재 JobQ에 Push하는 과정에서LCurrentJQ를 확인하여 GlobalQ에 넣을지, 스스로 실행할 지를 결정하는 것으로 보입니다. TLS는 각 Thread마다 별개의 주소 공간으로 소유하고 있는 것처럼 동작한다고 이해하고 있습니다.한 thread에는 실행 흐름이 하나인 것으로 알고 있는데LCurrentJobQueue가 nullptr이 아닌 상황에서 Push가 발생할 수 있나요?Execute를 실행하는 thread의 LCurrentJQ만 nullptr이 아닐 것 같은데 Execute가 실행 중인 thread라면 Push를 동시에 실행할 수 없을 것으로 생각됩니다. ㅜㅜ
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
SendBuffer Pooling 관련 질문있습니다.
여기서 다 썼으면 버리고 새거로 교체할 때 교체하지 않고 그냥 Reset만 호출해서 _usedSize를 0으로만 해줘도 되지 않을까 했었는데 WSASend를 호출하는 과정에서 아직 예전 버퍼가 날아가면 안되는 상황이 있기 때문에 새로 할당해준다. 가 맞게 이해한 부분인가요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
클라에서 서버 전향
안녕하세요 루키스님, 언제나 좋은 강의 감사합니다. 강의와 관련된 질문이 아니라 죄송하지만 따로 여쭤볼만한 곳이 없어 이렇게 질문 드립니다. 저는 4년차 클라이언트 프로그래머입니다. 쥬신 아카데미 출신으로 운 좋게 취업에 성공했지만 어쩌다보니 유니티로 커리어를 시작하게되어 지금까지 유니티 엔진을 사용하는 모바일 게임 프로젝트에서만 일하고 있습니다. 어렸을때부터 주로 온라인게임을 플레이 해왔었고 이직하고 싶은 팀도 MMORPG팀이지만 그런 곳은 주로 언리얼 엔진을 사용하다 보니 이직이 쉽지 않더군요 ㅠㅠ이러다 평생 모바일 수집형 게임만 만드는게 아닌가란 걱정도 들고 지금 있는 회사보다 좀 더 좋은 회사로 가고 싶다는 생각도 있다 보니 어느 순간 서버에 생각이 닿았습니다.남의 떡이 더 커보인다는건 알지만 저희 팀에서도 반년째 서버 개발자가 구인이 되고 있지 않고 있다 보니(나름 규모 있는 회사입니다 ㅠㅠ) 더 그런 생각이 들었던 것 같습니다. 여튼 그렇게 루키스님 강의와 시중에 있는 서버 책을 보며 공부도 하고 서버를 연동해 게임도 만들어 보고 있지만 회사 일과 병행하며 전향을 준비하기에는 조금 벅찬감이 있는것같아 퇴직 후 1년정도 학원(프로카데미)을 다닐까 고민하고 있습니다. 1년이 짧은 시간은 아니다 보니 회사 일을 병행하면서 준비를 계속할지 아니면 학원에 들어갈지 망설여지고 있는데 조언 부탁 드립니다 ㅠㅠ나이는 27살이고 연봉이 높은 편은 아니다 보니 이직 후 신입 연봉을 받게되더라도 크게 아쉬움은 없을 것같습니다..
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
책 추천 문의드립니다.
우선 좋은 강의 감사합니다. 강의 초반 Modern C++ Design 책 추천을 주셨는데요, 이 외에 추천 해주실 책이 있으신지 문의 드립니다. (개인적으로 추천해주시는 top5책을 알고싶습니다.) 코드를 짜면서 생소한 패턴를 만날때다마 블로그에 떠도는 글을 보면서 알음 알음 알아가고 있는데요, 혹시 이러한 지식들을 체계적으로 쌓고 싶은데, 해당 책 외에 추천 가능하실까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
sendQueue 관련 질문입니다.
강의를 들으며 1send + sendQueue를 사용하는 경우의 장점은 1.더 많은 클라이언트를 받을 수 있다. 2.TCP 헤더가 적게 붙어 네트워크상 이점이 있다. 이렇게 생각했습니다.하지만 실제로 서버를 만들다 보니 동시 send가 불가능해 대부분의 시간을 lock에 소비했고, n send에 비해 동시접속 가능한 클라이언트 수가 줄어들었습니다.그럼 2번 장점이 확실한가? 궁금해서 wireshark로 확인해 봤을 때 별 차이가 없었습니다. 큐에 넣지 않고 WSAsend를 많이 호출해도 os가 패킷을 뭉쳐 보내는 것 같습니다. 지금 방식의 장점이 궁금합니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Memory Pool#2 삭제 Lockfree stack 과의 값 교환 차이가....?
이전에 Lock free stack 에서는 ABA problem 이 발생하지 않는다고 별도로 들고 있었기 때문이라고 하셨는데 이전에도 링크드 리스트 처럼 포인터를 들고 있던 방식이고 현재 이것도 그것과 유사한 방식인데 왜 이전에는 ABA 가 발생하지 않았다고 하는건지 잘 이해가 가질 않네요 이전 lock free stack 에서 삭제 할때의 로직과 크게 달라보이진 않는것 같은데요..이전 lock free stack 에서도 ABA Problem 이 발생하지 않나요?차이점이 명확하게 어떤 부분인지 모르겠습니다..답변좀 부탁드려요! Memory Pool#2 시간은 26:55 초에서 정도에서..
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
강의 수강 후 개인 프로젝트 적용
수강 후, 대학 동아리 수준에서 내용을 제대로 습득했다는 전제 하만든 게임과 서버를 연동할 능력을 갖출 수 있나요?동아리에서 mmorpg를 만들어 보려 하는데 서버를 담당하게 되어 미리 공부하려 합니다.
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
SendBufferRef에 대하여 질문 있습니다.
안녕하세요 루키스님이번 SendBuffer 강의를 들으면서 궁금한 것이 생겨 질문 드립니다.SendBuffer에 자기 자신에 대한 스마트 포인터를 갖도록 해주어 Reference Counting을 해주었는데, 이번 강의의 코드를 복습하면서 분석하다 보니 '왜 SendBuffer에 RefCounting이 필요한가?' 에 대한 의문이 생겼습니다. 일단 제가 이해한 Send의 흐름은 다음과 같습니다.GameSession에서 SendBuffer를 생성하여 원하는 데이터를 복사하여 Send를 호출하면 SendQueue에 일단 Push하여 데이터를 쌓아 놓습니다.그 때 어떠한 쓰레드에서도 그 세션에 대한 RegisterSend를 수행하고 있지 않다면 해당 쓰레드가 RegisterSend를 수행하는데 이때까지 쌓인 데이터를 SendEvent의 버퍼에 담아 WSASend를 수행합니다.그런 다음 IocpCore에서 완료 통지를 받으면 Worker 쓰레드가 Dispatch를 수행하여 ProcessSend를 수행하면서 이 때 SendQueue에 데이터가 더 있다면 그 쓰레드가 RegisterSend를 수행합니다.위의 흐름이 제가 이해한 내용인데 결국 한번에 하나의 RegisterSend가 진행되도록 하는 것이 핵심이며 한 번에 하나만 실행하기 때문에 SendEvent도 재 사용 가능한 것이라고 생각합니다. 그렇다면 이 세션에 대한 SendEvent는 Send되고 있는 동안에는 멀티쓰레드 환경에서 안전하다고 생각 되는데 그렇다면 SendEvent에 담긴 SendBuffer도 안전하여 사라질 걱정을 하지 않아도 되는 것 아닐까 싶습니다.즉, WSASend를 한 번에 하나의 쓰레드만 수행하기 때문에 SendEvent도 재 사용이 가능하고 그 속에 담긴 SendBuffer도 멀티쓰레드 환경으로부터 안전하기 때문에 SendBuffer의 RefCounting이 왜 필요한 것인지 궁금합니다.
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
리눅스에서 이벤트 사용
쓰레드 강의파트에서 리눅스 영역을 고려해 <windows.h>를 사용하지 않고 <thread>를 사용한다고 하셨는데 이벤트는 <windows.h> 헤더를 대체할만 것이 있을까요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
신규 강의 질문
안녕하세요 루키스님! 유튜브에 온라인 출판사 영상을 보고 궁금하게 생겨서 이렇게 질문드려요! 유튜브 영상에서는 WinAPI-D2D-D3D 커리큘럼, UE 커리큘럼, Unity 커리큘럼 이렇게 3개를 구상중이라고 하셨는데 C++ IOCP + UE5 연동 강의는 일정이 어떻게 되는지 알 수 있을까요? ㅠㅠ
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
생각을 해봤는데 이해가 잘 되지않습니다. 질문 드립니다
안녕하세요. 지금 ReadLock WriteLock 강의듣고 혼자서 구현해보는 연습중에 궁금한점이 있어서 문의드립니다. Main부분에서 for (int i = 0; i < 2; i++) { threaManger->Luncher(ThreadWrite); } for (int i = 0; i < 5; i++) { threaManger->Luncher(ThreadRead); } 고유 스레드 아이디를 부여해서스레드 2개는 Write("스레드 아이디" 1,2)스레드 5개는 Read ("스레드 아이디" 3,4,5)일을 시키는데이렇게 되면 Read만 하는 스레드는 ReadLock만 잡고Write만 하는 스레드는 WirteLock만 잡게 되어서1번 아이디의 스레드(Write)가 Read Lock을 잡을 수 없지 않나요?아래 코드에서 Readlock 함수를 보면WRITE_THREAD_MASK를 씌어서 threadId를 비교하는데 이 부분은 실행 안될 거라고 생각되는데 맞나요?실제로 디버그에서 ReadLock에 포인트를 잡고 봤는데 브레이크 포인트에 걸리지는 않았습니다.제가 궁금한 걸 글로 쓰려니 잘 정리가 안돼서 죄송합니다.질문을 요약하자면1.ReadLock을 잡는 스레드의 id는 WriteLock을 잡는 스레드 id와 똑같을 수가 있나요? // ReadLock const int lockThreadId = (_lockFlag.load() & WRITE_THREAD_MASK) >> 16; if (lockThreadId == SharedThreadId) { _lockFlag.fetch_add(1); return; } // WriteLock const int lockThreadId = (_lockFlag & WRITE_THREAD_MASK) >> 16; if (lockThreadId == SharedThreadId) { _writeCount++; return; }
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
pushOnly 인자를 주는 이유
JobQueue::Push 에서 pushOnly를 추가해야 하는 이유를 잘 모르겠습니다. JobQueue::Push 함수가 실행되었다는 것은 이미 예약한 시간이 되어서 실행되어도 좋은 Job이 JobQueue에 Push된다는 뜻이 아닌가요? 지금 당장 실행되어도 좋은 Job을 Push 하려는데, 왜 굳이 JobQueue::Execute를 건너뛰고 GlobalQueue::Push를 호출해서 한 타이밍 늦게 Job을 실행시키는지 잘 모르겠습니다.
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
하나의 쓰레드에만 일감이 몰리는 현상이 왜 안좋은가요?
하나의 쓰레드가 여러 개의 JobQueue를 점유하는 현상이 안좋은 이유는 알겠습니다. 다른 쓰레드가 다른 JobQueue의 Job들을 처리하지 못하게 되니까요. 그런데 모든 쓰레드가 모든 일감을 처리할 수 있는 만능 일꾼이 된 상황에서, 하나의 쓰레드가 하나의 JobQueue를 오래동안 잡고있는 현상이 왜 안좋은지는 잘 이해가 안갑니다. 어차피 하나의 쓰레드가 붙잡고 해야할 일이 아닌가요? 동시에 여러 쓰레드가 처리 가능한 것도 아닌 것 같구요... 예를 들어, 쓰레드 A, B, C가 있다고 해봅시다. 쓰레드 A가 JobQueue 'ㄱ'를 점유하고 계속 작업을 하고 있습니다. 쓰레드 B와 C는 'ㄱ'과 관련된 일은 모두 A에게 몰아주고 나머지 작업들을 처리하고 있습니다. 그런데 A의 'ㄱ'점유가 너무 길어져서 'ㄱ'의 점유를 B에게 넘겨주었습니다. 그리고 A는 B와 C가 하던 것 처럼 나머지 작업들을 처리하게 되었습니다. 그럼 결국 'ㄱ'의 점유가 A에서 B로 넘어갔을 뿐 달라진 것이 없지 않나요? 오히려 쓸 데 없는 스위칭 비용만 발생한 것이 아닌가요?
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Receive 에 관해 질문 드립니다.
안녕하세요. 정말 신입 서버의 교과서 같은 강의라서 잘 보고 있다가 문득 궁금한 점이 생겨 질문 드리게 되었습니다. 제가 이해하기로는 TCP 는 Stream 방식이라서 100 byte 의 데이터를 send 하는 경우, 한 번에 받는다는 보장이 없어 20, 30, 50 이렇게 끊어서 받는 경우가 충분히 있을 것 같은데.. 현재 강의해서 제작된 RecvBuffer 를 사용함과는 무관하게 해당 현상을 해소하는 부분이 아직 안 보이는 것 같은데 이 부분은 따로 처리를 해야되는 부분인가요? 추후에 OnRecevie 함수 내부에서 처리를 하게끔 만드는 것인지, 아니면 해당 현상에 관련된 작업은 굳이 안해도 되는 것인지 궁금하여 질문드려봅니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
궁금한 점이 있습니다.
강의 초반부에서 Session::Send()를 수정해주셨는데 { WRITE_LOCK; _sendQueue.push(sendBuffer); } if(_sendRegistered.exchange(true) == false) RegisterSend(); 이렇게 작성하면 안되는 것일까요? 별도로 스택 변수를 사용해야 되는 이유가 있는지 궁금합니다. 멀티스레드 개념이 잘 안잡혀서 번거롭게 사소한 것까지 여쭤봐서 죄송합니다..
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
reinterpret_cast질문이있습니다.
template<typename T> BufferWriter& BufferWriter::operator<<(const T& src) { *reinterpret_cast<T*>(&_buffer[_pos]) = src; _pos += sizeof(T); return *this; } reinterpret_cast c++강의에서 아주 강력한 변환 포인터랑 정수사이도 변환이 가능하고.. 다 가능한 변환 느낌이었는데 앞에*를 붙여주는 이유가 궁금합니다. *reinterpret_cast<T*>(&_buffer[_pos]) = src; =========================== T*로 변환하는데 src가 참조라서 *를 한번 더 붙여주신건가요?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
상속관계 복사부분 질문이있습니다.
1. // 상속 관계 복사 template<typename U> TSharedPtr(const TSharedPtr<U>& rhs) { Set(sticta_cast<T*>(rhs._ptr)); } 강의에서 TSharedPtr클래스의 상속관계복사부분이 이해가 조금 부족한 것같습니다. 부모 자식관계에서 받아온 값들을 다시 static_cast<T*>로 하면 복사가 정상적으로 되는건가요? 2. 강의에서 wraight = nullptr 이 부분은 실제로 wraight = WraightRef(nullptr); 로 되어있어서 TSharedPtr(T* ptr) { Set(ptr); }이 호출된 후 복사 연산자가 호출된다고 말씀하셨는데 실제 디버깅을 해보니 복사가 아니라 이동쪽으로 브레이크 포인트가 타고있었는데 같은 맥락인건가요 ?
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
오버로딩 new
오버로딩 new가 궁금합니다 매개변수로 타입 size_t인데 어떻게 생성자로 new Knight()가 받아지는건가요? 디어셈블리에서도 해당 크기가 받아지는데 그 부분이 왜그런지 궁금합니다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
소켓프로그래밍 질문드립니다.
현재 락프리까지 듣고 소켓프로그래밍이 궁금해서 바로 넘어 왔는데 현재 게임서버쪽이 ws2에러가 재정의 에러가 나서 질문드립니다. 현재 msdn으로가서 오타도 확인하고 안되서 루키스님의 소스도 복붙했는데 제 visual에서 에러가 발생하는데 혹시 threadmaanager 강의쪽에서 추가하신 것이 있어서 그런건가요? 만들어가요. - 잠깐! 인프런 서비스 운영 관련 문의는 1:1 문의하기를 이용해주세요.
-
해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
AcceptEx 질문있습니다.
AcceptEx가 실패가 나는 경우 즉 , AcceptEx호출 자체가 false가 나고, 이때 GetlastErrror가 WSA_IO_PENDING이 아닌경우나 , AcceptEx의 호출로 IOCP 에서 Pending중일때 모종의 이유로 GQCS에서 AcceptEx pending에 대한 실패가 리턴되는경우 listen socket이 close되었거나, 어찌되었든 더이상 유저를 받지못하는 상황일 수 있는데 이럴때 서버에 강제로 CRASH를 내도록 해도 될것같은데, 혹시 이렇게 하면 안될 이유가 있을까요?? (AcceptEx를 호출할때 close된 session 소켓을 전달하는 경우는 없고, AcceptEx의 호출결과로 IOCP 유저접속을 대기중인상태(Pending)일때 session socket이 close되거나 session이 삭제되는 일은 일체 없다고 가정합니다. 물론 listen socket은 닫힐 수 있지만, listensocket이 닫히면, 서버를 유지시켜줄 이유가 없다고 생각되긴 합니다.)