월 66,000원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Client에서 Send한 정보는 그럼
Client에서 Send한 정보는 그럼 Server에서 Recv 하지 않으면 Client 컴퓨터의 SendBuffer에서 대기하는건가요? 아니면 Server컴퓨터의 RecvBuffer에서 대기하는건가요??
- 해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
SetReuseAddress 보안문제
MSDN을 살펴보니까 ReuseAddress 옵션 설정 시 보안 문제가 발생 할 수 있다고 써있는데 실무에서도 이방법이 사용 되나요?
- 미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
PROTOBUF 적용하고 빌드도 성공은 했는데 헤더 파일에서 에러가 발생합니다.
PROTOBUF_NAMESPACE_OPEN 인식이 안되고다른 에러들도 있는데 원인이 뭔지 몰라서 어떻게 해결해야 할 지 잘 모르겠습니다.빌드는 잘 되는데 .proto에 정의한 message 객체를 생성하고 값을 set 하려고 하는데 자꾸 에러가 생깁니다.syntax = "proto3";package example;message Person { string name = 1; int32 age = 2; repeated string hobbies = 3;} example::Person person; //사용자로부터 문자열을 입력 받는다. std::string name, hobby1, hobby2; std::cout << "이름: "; getline(std::cin, name); name.erase(name.find_last_not_of("\r\n") + 1); std::cout << "취미1: "; getline(std::cin, hobby1); hobby1.erase(hobby1.find_last_not_of("\r\n") + 1); std::cout << "취미2: "; getline(std::cin, hobby2); hobby2.erase(hobby2.find_last_not_of("\r\n") + 1); std::cout << "나이: "; int age; std::cin >> age; std::cin.ignore(); // 입력 버퍼 비우기 person.set_name(name); // 여기서 에러 person.set_age(age); person.add_hobbies(hobby1); person.add_hobbies(hobby2);
- 해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
스마트포인터를 활용한 설계에 대한 질문
안녕하세요 루키스님 프로젝트에 스마트포인터를 사용해보려고하는데 제가 생각한 설계가 맞는지 궁금합니다C++ 서버 강의에서 스마트포인터에 대한 설명을 들었는데 Shared_ptr은 상호참조문제가 있고 이를 해결하기 위해 Weak_ptr을 사용한다고 설명해주셨는데Weak_ptr이나 Shared_ptr을 잘 사용해서 상호참조로 인한 문제를 잘 해결하면 좋겠지만 프로젝트 크기가 커지다보면 상호참조 관계를 명확하게 파악하기 어렵다는 단점이 존재할수 있다고 생각합니다 그래서 제가 생각한 방법은 어떤 객체에서 다른 객체의 생명주기를 자신이 직접 관장한다면 shared_ptr 그렇지않다면 weak_ptr로 멤버를 두고 관리하고 shared_ptr인 멤버는 항상 weak_ptr로 반환하도록 하는게 좋지 않나라는 생각입니다 강의에서 설명해주신 Knight를 예로들어보면Knight끼리 서로를 타겟으로 지정할수 있다고 할때 Class Knightprivate :weak_ptr<Knight*> targetshared_ptr<Weaphon*> weaphon 위 코드를 예로들면 타겟 가능한 기사객체는 자기 자신이 생명주기를 관장하는 멤버가 아니기떄문에 weak로 두고 기사가 들고있는 무기의 경우는 기사가 죽을때 같이 사라지는게 자연스럽다고 볼수 있기 때문에 shared로 둬서 knight가 죽을떄 자연스럽게 같이 사라지도록 설계하고만약 대장간 같은데서 강화를 위해서 weaphon을 참조해야한다면 Knight에서 weak_ptr<Weaphon*> GetWeaphon() 이런식으로 설계해서 상호참조를 예방할수 있도록 설계하는것이 어떻겠냐는 생각을 개인적으로 해봤는데 이에대해서 어떻게 생각하시는지 궁금합니다
- 해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Spinlock에서 Compare exchange를 사용하지 않고
locked 값을 true, false로 바꿔주는 부분과 if문에서 lock을 검사하는 부분 만약 그 두부분을 원자적으로 실행시킬수 있다면 똑같이 스핀락으로 동작하도록 만들수 있을까요?
- 미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
안녕하세요 Echo서버 테스트 하고 있는데
주고받는 도중에 Send에서 애러가 뜹니다.어디가 잘못된걸까요??
- 해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
OT관련 질문
OT 1차시를 들어봤는데 비주얼스튜디오보여주시면서 다 ~~를 다 알아볼 수 있었다. 라고 하셨는데 이 전에 듣고 와야 하는 수업이 있나요? 그전 강의를 듣고와서 이미 전반적인 코드가 있어야 하는건가요?
- 해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
TestLock을 Template으로 만들경우
TestLock을 Template class 로 선언할경우typename을 type으로 명명한 상황에서TestRead에서의 _queue가 Empty일경우 반환값을 지정할 방법이 있을까요??
- 해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
TrypPop에서 oldHead를 delete 바로 할 경우의 충돌상황
TrypPop에서 oldHead를 delete 바로 할 경우 발생하는 충돌을 보고 싶어서 여러 번에 걸쳐서 돌려봤는데 발생하는 상황을 보지 못했습니다 이런 상황은 이론적으로 가능하나 굉장히 희박한 확률로 발생하는 걸까요??
- 해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5 는 언제 나오나요?
안녕하세요! 루키스님 [C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part5는 언제쯤 출시가 될지 궁금해서 이렇게 글을 남깁니다.입문자를 위한 UE5영상이 올라오고 있는데 해당 언리얼 영상 시리즈가 완료되면 출시가 될까요?
- 미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Reader Writer Lock 질문입니다.
W->R 락 순서는 허용R->W락 순서는 허용하지 않음인데요.두 상황 모두 허용하지 않아야되지 않을까해서 문의드립니다.W->R일 경우에도쓰고있는 있다는 것이 값이 바뀌고 있다는 것인데Read하는 스레드들이 쓰는 찰나에 전후 다른 값을 읽어가는 것은 문제가 없을까요??R->W를 허용하지 않은 경우처럼읽을 때 누가 값을 바꾸면 안되니 허용하지 않는것처럼R->W, W->R그게 그말 처럼 느껴져서 질문드립니다.
- 해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
CSpinLock 코드 작성중 원리에 대해서 의문점이 들어 질문 드립니다.
void CSpinLock::lock(){ bool expected = false; bool desired = true; while (_locked.compare_exchange_strong(expected, desired) == false) { expected = false; }}SpinLock의 해당 코드에서 _locked의 값이 true일때, expected의 값이 초기에는 false임으로, 해당 반복문을 통과하지 못하고 기다립니다. 그런데 expected가 locked의 값인 true로 바뀌므로 이를 반복문 내에서 expected = false; 값으로 변경해주는데, expected의 값을 false로 변경해주기 전에 true인 locked의 값이 들어오면 아직 expected의 값은 변경되기 전이므로 SpinLock을 빠져 나올 수 있지 않을까요?코드를 실행해보니 SpinLock이 잘 실행되고 있는 것은 확인했지만, 머리속에서는 납득하지 못한 의문점이 멤돌아서 이렇게 질문 드립니다.
- 미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
TryPop()함수 중 _head와 _tail이 같을 때 ReleaseRef()를 해야하나요?
강의 코드를 똑같이 따라하는 도중 TryPop()함수에서 무한 루프에 빠지는 것을 확인하였습니다.위의 이미지 중 주석처리 한 곳이 TryPop()중 무한 루프에 빠지게 하는 함수입니다._head와 _tail이 같을 경우 ReleaseRef()에 들어갑니다. 하지만 초기 internalCount는 0이고 unsigned입니다.때문에 저의 컴퓨터 환경기준 --를 진행할 시 '1073741823'으로 바뀌면서 무한에 가까운 루프에 빠지게 됩니다.위의 이미지 같이 주석처리 할 경우 강의의 예시처럼 잘 진행되는 것을 확인 하였습니다.혹시 저 부분을 주석처리 해도 되는지, 안된다면 위와 같은 상황에서 어느 부분을 수정해야 하는지 확인해 주실 수 있으실까요?
- 해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
GIocpCore에서 Dispatch할 때
iocpObject Dispatch할때 어떻게 자동으로 리스너 Dispatch로 들어가는건가요?
- 미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
클라이언트 연동 강의
안녕하세요 루키스님 제가 c++ icop 멀티스레드 환경에서 서버를 제작하고 원래 언리얼로 클라이언트 만들어서 연동하려했는데 자료가 부족해서 유니티 강의를 참고하려고합니다.Part7 : MMORPG 컨텐츠 구현 (Unity + C# 서버 연동)Part9 : MMORPG 컨텐츠 구현 (DB 연동 + 대형 구조 관리 + 라이브 준비)두가지의 강의를 들어보려고하는데 유니티와 c#에 대한 지식이없어도 들을수있을까요?언리얼 연동에 도움이 되는강의가 더 있을까요?Part5 : 데이터베이스(SQL Server) 강의는 수강하려고합니다.
- 미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
소켓 프로그래밍 질문 있습니다!
msdn 문서도 찾아보면서 공부 중인데, 제가 이해한 게 맞나 확신이 안가서 질문 드립니다!서버가 계속 listen 상태이고 여러개의 클라이언트들이 연결을 하고 연결을 끊는 과정에서도 서버가 listen 상태를 계속 유지하게 하려면 accept() 함수를 while 문으로 반복적으로 받게 한다 (여러 클라이언트들의 연결을 수용하기 위함) accept() 함수로 백로그 큐에 있던 수신정보?연결대기정보?를 pop하여 새로운 소켓을 생성한다내부에 또다른 while 문으로 생성된 새로운 소켓을 활용해 송수신을 한다accept() 함수를 호출하는 while문 마지막 부분에 생성된 소켓을 close 한다.이렇게 하는게 맞을까요??제가 이렇게 코드를 짠 것 같은데, 서버를 실행시키고 한개의 클라이언트를 실행시켜서 송수신을 하다가 클라이언트를 종료시키면 서버도 같이 종료되는 것 같아서요...여러 클라이언트를 실행시켜도 처음 실행시킨 클라이언트만 송수신이 가능하더라구요 ㅠㅠ(제가 코드를 잘못 짠 걸수도 있습니다 ㅎㅎ;;)아래는 서버와 클라이언트의 주요 소스코드 부분입니다[Server]// 윈속 초기화와 socket(), bind(), listen() 함수 생략 while (1) { // accept() clntAddrSize = sizeof(clntAddr); clntSock = accept(listenSock, (SOCKADDR*)&clntAddr, &clntAddrSize); if (clntSock == INVALID_SOCKET) ErrorHandling(L"accept() error"); // 접속한 클라이언트 정보 출력 wprintf(L"\n[TCP 서버] 클라이언트 접속 : IP 주소 = %s, 포트 번호 = %d\n", inet_ntoa(clntAddr.sin_addr), ntohs(clntAddr.sin_port)); // 클라이언트와 데이터 통신 while (1) { recvLen = recv(clntSock, (char*)message, sizeof(message), 0); if (recvLen == SOCKET_ERROR) ErrorHandling(L"recv() error"); else if (recvLen == 0) break; // 받은 데이터 출력 message[recvLen / 2] = L'\0'; wprintf(L"[TCP/%s:%d] : %s\n", inet_ntoa(clntAddr.sin_addr), ntohs(clntAddr.sin_port), message); // 데이터 보내기 strLen = wcslen(message) * sizeof(wchar_t); if (send(clntSock, (char*)message, strLen, 0) == SOCKET_ERROR) ErrorHandling(L"send() error"); } closesocket(clntSock); wprintf(L"[TCP 서버] 클라이언트 종료 : IP 주소 = %s, 포트 번호 = %d\n", inet_ntoa(clntAddr.sin_addr), ntohs(clntAddr.sin_port)); } closesocket(listenSock); WSACleanup();[Client]// 윈속 초기화와 socket(), bind() 함수 생략 // connect() if (connect(hSocket, (SOCKADDR*)&servAddr, sizeof(servAddr)) == SOCKET_ERROR) ErrorHandling(L"connect() error"); else { printf("Connected...........\n"); } // 서버와 데이터 통신 while (1) { // 데이터 입력 wprintf(L"data input : "); if (fgetws(message, BUF_SIZE, stdin) == NULL) break; // '\n' 문자 제거 strLen = wcslen(message); if (message[strLen - 1] == L'\n') { message[strLen - 1] = L'\0'; strLen--; } if (wcscmp(message, L"q\n") == 0 || wcscmp(message, L"Q\n") == 0) break; //데이터 보내기 recvLen = 0; recvLen = send(hSocket, (char*)message, strLen * 2, 0); if (recvLen == SOCKET_ERROR) { ErrorHandling(L"send() error"); break; } printf("[TCP 클라이언트] %d 바이트를 보냈습니다.\n", strLen); while (recvLen < strLen * 2) { recvCnt = recv(hSocket, (char*)&message[recvLen / 2], BUF_SIZE - 1, 0); if (recvCnt == SOCKET_ERROR) { ErrorHandling(L"recv() error"); break; } else if (recvCnt == 0) break; recvLen += recvCnt; } message[strLen] = L'\0'; printf("[TCP 클라이언트 %d 바이트를 받았습니다.\n", strlen); } closesocket(hSocket); WSACleanup();
- 미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
데드락 어떻게 해결할 지 궁금합니다.
안녕하세요. Rookiss 강사님.덕분에 강의 아주 감사히 잘 들어가며 배우고 있습니다.다름이 아니라, 강의 중, 데드락 프로파일러를 이용하여, lock 간 사이클 여부를 확인하여사전에 어느 정도 사전에 예방 가능하지만 그래도 다 막을 수는 없다고 하셨는데,막상 발견된다면 데드락을 해결하는 것은 어렵지 않다고 알려주셨습니다. 혹시, 데드락 프로파일러를 통해 발견되지 않을 경우,데드락이 발생했는지 어떻게 확인하고, 데드락이 발견되면 어떻게 해결하는 지 궁금합니다. 스스로 생각하기로는 스핀락의 경우, 데드락이 발생하게 되면 뺑뺑이를 계속 돌게 될테니CPU가 증가하는 모습으로 나타날 것으로 보이려나 싶네요 혹여나 강의 중에 설명 주셨는데, 재질문 드리는 거라면 정말 죄송합니다.항상 좋은 강의 감사합니다.
- 미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
std::future에서 사용되는 쓰레드의 개수
std::future에서 비동기적으로 함수를 처리하기 위해서 사용하는 쓰레드는 미리 생성된 쓰레드를 통해서 처리하는 건가요?만약, 미리 생성된 쓰레드를 통해서 처리한다면 미리 생성된 쓰레드의 개수는 알 수 있나요? 그리고 해당 쓰레드의 개수도 수정할 수 있을까요?답변 부탁드립니다. 감사합니다.
- 미해결[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
싱글스레드가 안전한 이유?
싱글 스레드가 멀티스레드 이슈로부터 안전한게 다른 스레드의 개입이 없어서라고 알고있습니다.멀티코어 다중 스레드 PC에서 싱글스레드 프로그램을 동작시킨다 가정합니다.싱글스레드 환경에서 메인스레드 한개만 동작할것이고 스레드 아이디가 123이라 치고싱글 스레드 환경에서 변수 a가 있다치고 무한루프로 증가 시킨다고 칠때 컨텍스트 스위칭이 일어나도 a라는 변수는 무조건 스레드 아이디 123이고 같은 코어에 있는 스레드가 동작시키는 건가요??컨텍스트 스위칭 과정에서 운영체제가 스레드를 맘대로 할당해 주는 것으로 알고 있는데 다른 코어에 잇는 스레드를 할당해 줄수도 있지 않나해서요.그럼 다른 코어에 있는 캐시 등에 접근 가능하여 가시성, 코드 재배치 문제가 잇지 않을까합니다
- 해결됨[C++과 언리얼로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
PacketSession 강의에서 LOCK 크래시 관련
좋은 강의 감사합니다! 해당 강의에서, 다수의 클라이언트 세션이 접속된 상태에서 클라이언트 연결을 끊었을 때, 크래시가 나는 부분을 강의를 멈춰놓고 파악을 해 보았는데요, 이 경우 디스커넥트 이벤트가 발생하면서 OnDisconnected()가 호출되고, GameSessionManager()의 Remove() 함수가 다른 스레드에서 호출될 수 있다는 사실까지는 파악해서, _sessions.erase(session);이 코드가 문제가 된 것 까지는 파악했습니다.그런데 sessions.erase(session); 코드와, 아래의 session에서 루프를 돌만서 Send를 시키는 부분은 같은 WRITE_LOCK으로 보호가 되고 있는 상태라, 우선 루프를 끝까지 돌아 각 세션에 대한 send가 끝난 후 스코프를 빠져나가 WRITE_LOCK이 풀린 후 _session.erase()가 일어날 것이라고 생각해서 이 부분은 문제가 아닐 거라 생각했고, 결국 문제를 찾지 못하고 강의를 들었는데요, 강의에서는 이 부분에 대해서 따로 설명이 없는 것 같아, 왜 저 부분의 WRITE_LOCK 이 문제가 되었고, 루프를 도는 도중에 erase가 일어난 것인지 궁금합니다.