묻고 답해요
164만명의 커뮤니티!! 함께 토론해봐요.
인프런 TOP Writers
-
해결됨[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: 게임 서버
Job큐를 실행하는 스레드 질문있습니다.
Job을 Pop해서 실행하는 스레드는 1개인데 Job을 만들어서 Push하는 스레드는 여러개인것으로 보이는데 이렇게 하면 결국 Job이 가득 차서 실행이 밀릴것 같은데 어떻게 하나요?
-
해결됨[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 게임 개발 시리즈] Part9: MMO 컨텐츠 구현 (DB연동 + 대형 구조 + 라이브 준비)
안녕하세요. 질문드립니다.
안녕하세요. accountserver 구현 후 외부 접속을 해보고 있는데 서버를 실행중인 피씨와 다른 피씨에서 인터넷 창에 아이피를 입력 하면 잘 되는 것 같은데 유니티에서 실행하면 에러가 납니다.관련해서 아시는 것이 있다면 답변 부탁드리겠습니다.
-
해결됨[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 게임 개발 시리즈] Part9: MMO 컨텐츠 구현 (DB연동 + 대형 구조 + 라이브 준비)
유니티에서 클라이언트 빌드후 실행하면 맵 로드가 안됩니다.
안녕하세요, 이번 강의에 올라온 코드로 유니티에서 빌드해서 실행을 했더니 맵등이 로드되지 않습니다. 빌드하려면 별도의 설정등이 필요한건가요?
-
미해결[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: 게임 서버
StompAllocator 메모리 오버플로우 감지에 대해 질문드립니다
강의와 같이, 자신의 페이지를 넘어선 메모리에 접근하면 "쓰기 엑세스 위반"이라는 에러가 뜨는 상황인데. 이 때 만약, 오버플로우로 접근하는 바로 그 다음 페이지가 "쓰기 권한이 있는" 페이지 였다면 오버플로우를 잡아내지 못하는건가요? 아니면, 엑세스 권한과 상관없이 단순히 페이지 범위를 벗어났기 때문에 에러를 주는 원리인가요?
-
미해결[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이 닫히면, 서버를 유지시켜줄 이유가 없다고 생각되긴 합니다.)
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
저가 정리한게 맞는지가 궁금합니다
요약한게 맞는지 확인해주실 수 있나요? 1. Pop은 현재 head를 따로 oldHead로 저장하고, 이것이 nullptr이 아니란 소리는 head가 존재한다는 뜻, 즉 1개 이상 스택에 값이 존재한다는 뜻임 2. 스택에 값이 1개 이상이면 oldHead는 nullptr이 아닐 것이고 pop을 한번 했을 때 oldHead에 head가 제대로 값이 들어갔다면 while문을 통과하면서 _head=oldHead->next;가 원자적으로 실행되고, 아래쪽을 쭉 실행하다가 TryDelete 함수가 호출될 것임 2-1. 이때 만약 다른 Pop 쓰레드들이 있다고 하면, 요놈들은 첫 Pop에서 _head가 oldHead->next로 바뀐것으로 인해 while문을 통과하지 못하므로 oldHead=_head가 실행되어 다시 while문이 불려져서 다음 원소를 상대로 pop을 진행함 -------------------- 이후는 TryDelete입니다 3. popCount가 1인 경우 : TryDelete가 실행되는 순간에도 popCount가 1이라면 아직은 Pop이 다른 쓰레드로 호출되지 않은 상태임. 3-1-1. pendingList를 읽어 삭제하려고 하는데, 이걸 읽었는데도 popCount가 아직 1이라면 Pop이 pendingList를 읽는 사이에 한번도 호출되지 않은 것이므로, 읽은 pendingList와 연결된 모든 노드를 이참에 삭제함 3-1-2. pendingList를 읽어 삭제하려고 하는데, 이걸 읽은 사이에 popCount가 증가하여 Pop이 다른 쓰레드에서 호출됐다는 걸 알았으니 읽어들인 pendingList를 다시 돌려놓는다. 3-2. pendingList도 다 삭제햇으니(돌려놨으니) 현재 노드를 삭제해주면 된다. 4. popCount가 1 초과인 경우 : TryDelete가 실행되는 순간에 popCount가 1을 넘어버렷다면, Pop이 다른 쓰레드에서 호출된 상태이므로 지금 당장 삭제하지 말고 삭제 예약만 해놓도록 한다.
-
미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
RegisterSend를 하나의 스레드만 수행하는 이유가 궁금합니다.
큐에서 데이터를 꺼내는 작업 자체가 여러 스레드가 동시에 들어가도 의미가 없거나 wsasend가 스레드 안전하지 않아서 그런건가요? recv도 그렇고 send도 그렇도 하나의 세션에 대한 본질적인 작업은 사실상 하나의 스레드만 수행할 수 있다고 이해하면 되는걸까요?(사실상 여러 스레드가 접근해도 실질적인 세션의 공유자원(버퍼 등등)에 대해 순차적으로 접근할 수 있으므로 )