월 17,600원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
ArraySegment 질문입니다
안녕하세요 ㅎㅎ ArraySegment 의 신기한 점을 발견하고 질문드립니다. Q.1 Session.cs에서 RecvBuffer 객체를 생산하고 다음과 같이 _recvArgs.SetBuffer의 인자로 WriteSegment의 반환값을 넣어주고 있습니다. WriteSegment의 반환값이 _buffer의 값을 이용해 새로운 인스턴스를 생성했다고 생각했습니다. 왜냐면 new를 통해 만들었으까요.. 일종의 값의 복사만 일어났다고 생각을 했거든요.. 근데 로직상 _recvBuffer.WriteSegment의 반환값이 RecvBuffer 객체의 맴버변수인 _buffer에도 영향을 주기에 가능하다고 생각하니 단순 값의 복사만 일어난건 아니라고 생각했습니다. 실제 테스트 해보니 _buffer를 통해 만든 newBuffer의 값을 변경하니 _buffer의 값 또한 변경됐습니다.. 이게 어찌 가능한 일인가요? ArraySegment 생성자의 첫번째 인자가 신비로운 문제의 해답인가요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
세션과 소캣 질문
안녕하세요 ㅎㅎ 세션과 소켓에 이 정확히 무엇인지 이해가 잘 안돼서 질문드립니다. 제가 이해한걸 정리하면 소캣은 서버와 클라가 통신할 수 있는 수단 혹은 통로라고 생각합니다. 그렇다면 세션은 무엇인가요? 소캣을 포함하며 구조적으로 설계가 잘 된 사용자 정의 인터페이스라고 봐도 되는건가요?
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
SendBuffer 참조에 관하여
멀티 쓰레드 환경에서 SendBuffer을 참조하여도 읽기만 하기 때문에 문제가 없다는 것은 알겠습니다만, 만약 Session의 _sendQueue에 Enqueue 되어있고 아직 처리되지 않은 상태에서 SendBufferHelper.Open에서 SendBuffer의 FreeSize보다 더 큰 크기를 인자 값으로 한다면 SendBuffer을 새로 만들어버리는데 이 경우에는 문제가 발생하지 않나요?
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
서버 흐름에 있어서 궁금한점이 있습니다
안녕하세요 SendBuffer까지 따라 해보고 전체적인 흐름을 그려보는 도중 궁금한 점이 생겨 질문드리게 되었습니다. Listener 소켓에서 OnAcceptCompleted 함수의 마지막에서 다시 등록(RegisterAccept)을 해주는데요. 이 부분에 무한 루프를 넣어서 다시 등록하는 과정을 거치지 않도록 해보았습니다. 따라서 더미 클라이언트 한 명이 OnAcceptCompleted에서 RegisterAccept를 호출하지 못하기 때문에 더미 클라이언트를 하나 더 실행했을 때 동시 접속이 안되어야 할 것 같은데 접속이 되더군요. 질문1) 위와 같은 상황은 _listenerSocket.Listen 때문이 맞나요? 이 부분을 1로 수정하니 정상적으로 동시 접속이 안되더군요. 질문2) 만약 맞다면 Listen 함수를 통해 동시 접속자 수를 컨트롤하나요? 질문3) Listen(10)을 넣어 10명의 동시 접속자가 있다면 최소 필요 쓰레드의 수는 10개인가요? 즉, 쓰레드의 최소 필요 개수 = 접속자 수 = 세션 수 인가요? 질문4) 윗 내용이 맞다면 많은 수의 쓰레드가 존재하여도 문제없나요?(예를들어 동시접속자가 1000명이라면 최소 1000쓰레드 이상) 읽어주셔서 감사합니다.
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
lock과 send에 관해서
안녕하세요, 이전 질문 글에 비슷한 내용의 질문이 있었는데 조금 다른 부분이 궁금해서 질문글을 올립니다. 1. Send를 할 때 lock을 건다. (현재 _pendingList가 비어있으면, RegisterSend() 호출하고 이게 끝나야 lock이 풀리게된다. ) 2. RegisterSend에서는 SendAsync를 호출하는데 true라면, 1에서 잡은 lock은 바로 풀릴것이다. 그런데 만약 false가 되면 3으로 넘어간다. 3. OnSendCompleted 에서 lock을 걸려고 한다. 👉 이 때 2번에서 SendAsync가 false가 되어 3으로 넘어온 경우라면, 1에서 잡은 lock이 아직 안풀렸을 것 같은 데 잡을 수 있나? 3번의 질문 내용이 궁금합니다. (1번에서 lock을 잡은 상태로 2번을 호출했고, 2에서 SendAsync의 return 값이 false가 되어 3으로 넘어올 때가 궁금합니다.) 제가 비동기 프로그래밍이 익숙하지 않다보니 이해가 부족해서 이런 질문을 올리게 되었습니다.😁 (제가 아직 뒷쪽 강의를 다 듣지 않았는데, 뒤 쪽에 혹시 이런 설명이 나올까요..?) 감사합니다(__) public void Send(byte[] sendBuff) { lock(_lock) { _sendQueue.Enqueue(sendBuff); if (_pendingList.Count == 0) // 대기중인게 하나도 없으니 해라. RegisterSend(); } } void RegisterSend() { // _pendingList가 비어있을 때만 여기로 들어온다. //_pendingList.Clear(); //_sendArgs.SetBuffer(buff, 0, buff.Length); while(_sendQueue.Count > 0) { byte[] buff = _sendQueue.Dequeue(); _pendingList.Add(new ArraySegment<byte>(buff, 0, buff.Length)); } _sendArgs.BufferList = _pendingList; bool pending = _socket.SendAsync(_sendArgs); if (pending == false) { OnSendCompleted(null, _sendArgs); } } void OnSendCompleted(object sender, SocketAsyncEventArgs args) { // 예약한 pendingList 완료됨 lock(_lock) { if (args.BytesTransferred > 0 && args.SocketError == SocketError.Success) { try { _sendArgs.BufferList = null; _pendingList.Clear(); if(_sendQueue.Count > 0) // 보내는동안 누가 또 Queue에 쌓았다. { RegisterSend(); } } catch (Exception e) { Console.WriteLine($"OnSendCompleted Fail {e}"); } } else { Disconnect(); } } }
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Disconnect 함수의 임계영역
안녕하세요 ㅎㅎ 궁금증이 생겨 질문드립니다. 강의 21분에 "Disconnect 함수를 동시 다발적으로 실행하거나 같은 Thread가 두 번 한다면" 이라고 말씀하셨습니다. Q.1 Disconnect 함수를 동시다발적으로 실행할 수 있나요? 다르게 말하면 DisConnect함수가 실행하는 내용이 임계영역인가요? 여러번 고민해봤는데 Disconnect를 호출하는 OnAcceptHandler는 인자로 스레드마다 독립적으로 하나씩 가지고 있는 clientSocket을 받고 clientSocket으로 Session.Start(clientSocket); 을 통해 Session 클래스의 객체를 초기화 해주기에 임계 영역이 아니라고 생각합니다. 후자로 말씀하신 하나의 Thread에서 실수로 코드에 두 번 기입해서 Disconnect를 하지 않는 이상 별다른 문제가 없다고 생각합니다. Q.2 매번 코드를 작성할 때마다 임계영역인지 아닌지 고민하면서 코딩하다 보면 머리가 터질 것 같습니다. 선생님께서는 눈에 보이는 임계영역에만 상호배제를 해주고 후에 배포 전에 테스트 단계에서 문제가 발생하면 그때 수정하는것도 현명한 방법이라고 생각하시나요? 조언 부탁드립니다!!
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
GameRoom에 모아 놓은 작업 Flushed 된 개수가 160개인데 정상인가요?
안녕하세요 예제코드에서는 Flushed 100 item인데 제가 실행했을때는 Flushed 160 item이더라구요 컴퓨터에 따라서 차이가 나는거죠? 제가 코드를 잘못 작성한건지 알고싶어요
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Parallel.Invoke 호출시 메인스레드 사용 이유
안녕하세요 의아한 점이 생겨 질문드립니다. 메인에서 MaxThread의 수를 3개로 지정한 상태에서 Invoke를 호출하고 ManagedThreadId를 확인하면 Invoke시에 메인 스레드인 1번을 사용하는 이유가 무엇인가요?.. MaxThread를 (1,1)로 설정해도 무조건 한 번은 메인 스레드를 사용하고 그 다음부턴 풀에서 스레드를 꺼내쓰더라구요.. 왜 한 번은 메인스레드가 사용되는건가요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
메모리 할당관련 질문
안녕하세요 ㅎㅎ 강의를 듣다가 여러 궁금증이 생겨 질문드립니다. Q1. 메모리 할당에 관한 질문입니다. 질문드리기 앞서 무성의한 변수 작성에 사과드립니다. static 변수(a)는 Data영역에 멤버변수(b)는 Heap영역에 멤버함수(Func)는 Code영역에 멤버함수 내에 존재하는 지역변수(c)와 t2는 Stack영역에 할당된다고 알고있습니다. 실제 Main에서 Test라는 클래스를 인스턴스화후에 메모리 구조에 대해서 몇 가지 질문드리고 싶습니다. Test t2 = new Test(); 이 코드를 실행하게 되면 Stack에 t2라는 변수가 생기고 Heap에 할당된 메모리를 가리키고 있을거라 생각합니다. 궁금한건 Func함수입니다. 질문속의 작은 질문들을 정리해서 말씀드리면 Q1.1 t2라는 변수를 통해서 저희는 멤버변수인 b에도 접근하고 Func라는 함수도 호출합니다. 다만 t2는 heap의 주소를 가리키는 포인터인데 heap영역에 있지 않는 Func라는 함수를 어떻게 가리키는건가요? 한 가지 추정을 해보면 heap어딘가에 Func의 Stack 시작점 주소를 저장할 공간이 있고 Stack에 함수가 할당되면 그곳으로 매핑을 시켜주는 건가요? Q1.2 Code영역이 궁금해서 검색하다가 지역변수는 함수 호출시에 Code영역에 저장되는 함수 정의를 활용하여 초기화 된다. 라는 글을 발견했습니다. Code영역에 함수가 정의된다는것과 Stack에 함수가 할당되는게 구체적으로 어떤 연관성이 있는지 이해가 잘 안됩니다.. 정의를 활용한다는게 어떤 의미안가요? Q1.3 클래스 내부에서 Static Test t1 = new Test(); 코드를 실행해봤습니다. static변수는 클래스가 메모리에 올라갈때 할당 된다고 배웠는데 t1이라는 변수가 Data영역에 할당되자마자 Heap에도 데이터가 할당되는건가요? Q1.4 이러한 메모리 할당에 대한 의문이 생기면 실제로 실험해보고 검증하고 싶은데 Stack Heap Data Code 영역을 실제로 확인할 수 있는 방법이 무엇인지 모르겠습니다 ㅠㅠ.. 디버깅처럼 이러한 것들을 확인할 수 있는 방법이 있을까요..?? Q2. ReaderWriterLock에 관한 질문입니다. WriteUnLock 부분에서 Exchange를 사용하지 않고 _flag = EMPTY_Flag;를 해주면 문제가 발생할까요? 제 스스로 고민해본 결과 WriteUnLock은 어쨋든 Lock을 잡은 상태에서만 호출을 한다고 가정했으니 임계영역이 아니라고 생각했습니다. 재귀적으로 호출을 해도 별 문제가 없다고 생각한건 싱글스레드가 독보적으로 호출할 수 있는 영역이니까요. ReadUnLock의 경우는 여러 스레드가 동시에 값을 변경하니 Interlocked.Decrement(ref _flag);를 호출하는게 맞다고 생각하는데 WriteUnLock을 _flag = EMPTY_Flag;이와 같이 작성해도 별 문제가 없을까요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Thread와 Context Switch에 대한 질문
안녕하세요 ㅎㅎ강의 잘 듣고 있습니다. Q1. 유저레벨 스레드? 커널레벨 스레드? 선싱님 강의를 수강하니 운영체제 수업에서 배운 내용들이 하나 둘씩 기억나서 매우 반갑네요. 제가 기억하는 내용을 적어보면, 일반적으로 IO나 인터럽트에 의해 발생하는 프로세스 문맥 교환과 매우 유사하게 쓰레드도 레지스터나 캐시의 정보들을 주 메모리로 옮기는 과정을 운영체제가 도맡아 담당하게 됩니다. 때문에 쓰레드간의 문맥 교환시에 Kernel모드로 진입한다고 말씀하신거겠죠. 궁금한점은 쓰레드의 구현 방식에 따라? (아마 유저 레벨 쓰레드와 커널 레벨 쓰레드로 구별하는 것 같습니다.) 문맥 교환의 비용이 차이가 난다고 어디선가 배운 기억이 납니다. 본 강의에서 사용한 쓰레드는 생성시 라이브러리 함수를 사용했고.. 아마 내부적으로 시스템 콜을 호출했고 결과적으로 유저가 아닌 Kernel이 스케쥴링하니 커널레벨 스레드인 것 같은데요.. 그렇다면 유저레벨 스레드라는건 어떤걸까요? 유저(개발자)가 문맥교환을 담당하고 스케쥴링도 담당하는, 모든걸 개발자가 도 맡아하는 스레드인가요? 실제 유저 레벨 스레드가 많이 사용되는 경우는 어떤 경우인가요? Q2. AutoResetEvent는 Kernel단으로 내려가서 문맥교환으로 인해 spinlock보다 성능이 저하될 수 있다고 말씀하셨습니다. 궁금한건 sleep 혹은 yield또한 cpu의 점유권을 포기한 상태에서 다른 스레드를 실행할 수 있기때문에 kernel로 진입후에 문맥교환이 발생하고 이에따른 성능 저하가 일어날 수 있을까요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
비동기 함수에 대한 질문
안녕하세요. Rookiss님 아래 질문 보다가 저도 궁금한점이 있어 댓글 남깁니다.ReceiveAsync는 예약이 걸렸을때 별도 Thread가 사용되는게 아니라 Windows 운영체제에서관리해주는것이라 답변해주신거 봤습니다. 첫번째 질문은 비동기 함수들은 전부 ReceiveAsync 처럼 별도 Thread가 아닌 Windows 운영체제에서 관리하는것으로 이해해도 될까요? 두번째로 C++ 네트워크 강의가 있다면 바로 구매해서 참고하고 싶지만.. 아직 제작하시는데 한참 남으신거 같아서 여기에 질문 남깁니다.. C++의 경우 Ioctlsocket()을 사용해서 블러킹 함수들을 논블러킹 함수로 사용할 수 있는걸로 알고 있습니다. 다만, C# Socket처럼 Async 라던가 Begin 같은 비동기 함수를 제공하지 않는데.. 논블러킹 함수로 직접 callback 비동기를 구현해야 하는건가요?
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Thread의 실행순서를 잘 이해한건지 모르겠어요
처음에 메인에서 t.Start();가 Console.WriteLine("Hello World!")보다 먼저 와 있어서 제 생각에는 먼저 Hello Thread!가 먼저 찍힐 줄 알았는데, 실행해보면 Hello World!가 먼저 찍히고 Hello Thread!가 찍히더군요. 그렇다는건 이 Thread라는 일꾼은 메인이 끝난 뒤에야 실행된다는 건가요??
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
콜백함수 질문 2
삭제된 글입니다
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
뜬금 없는 질문이지만 강사님 비주얼스튜디오 테마를 알수있을까요?
테마가 정말 마음에 드는데 혹시 알수있을까요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
게임소스
part3를 듣고 게임을 모작해보려고 하는데요 혹시 모작할 때 필요한 소스들은 어디서 구하는지 대략 좀 알 수 있을까요? 수업 외적인 질문이지만 비전공자라 어디 물어볼데가 없어서 여기다 질문드립니다
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Unity 관련 질문 드립니다!
안녕하세요 강좌를 다 보고 유니티로 움직이는 것을 연동해보고있는데요, 두명의 플레이어가 들어와있을때 자신의 움직임은 부드럽게 움직이지만 (간단하게 translate로 움직이게 해두었습니다) 상대방의 움직임이 부자연스럽게 뚝뚝 끊기며 렌더링되었습니다. 유니티 클라쪽에 상대방 position을 로그로 띄워보기도 하고 서버쪽에서 어떻게 위치값을 받는지 콘솔창에 띄우기도 해보았는데 결론적으로 S_BroadcastMove 나 C_Move 패킷의 위치값은 양쪽에서 잘 쓰고 받고 하는 것 같습니다.. 상대방의 움직임도 부드럽게 렌더링되면 좋겠는데 어떤 부분이 문제인건지 잘 모르겠습니다...!!
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Fuc<Session> _sessionFactory 관련
안녕하세요! sessionFactory 관련 질문드립니다! Listener에서 Accept 후 Session을 만들어주는 부분에서 _sessionFactory를 Func<Session>으로 만드는 이유가 궁금합니다! 단순히 Session _sessionFactory; 로 만들어 Init 할 때 인자를 Session 클래스로 받고 server에서는 만들고자 하는 Session을 람다식이 아닌 new GameSession()으로 만들어도 실행이 되더라구요..! 해당 부분이 추후 어떻게 구체적으로 사용될지는 잘 몰라서 이 부분을 Func로 만들어두는 이유가 궁금합니다..! 더불어 문법적인 질문이지만... Connector에서는 _sessionFactory에 구독할 때 _sessionFactory += sessionFactory 가 아니라 _sessionFactory = sessionFactory로 사용하시던데 사용에는 상관없는 부분일까요??
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
RegisterAccept에서 pending 여부 판단에 대하여
안녕하세요!! pending 관련하여 질문드립니다!! void RegisterAccept에서 굳이 if(pending == false) OnAcceptCompleted(null, args); 를 넣어주는 이유는 무엇인가요?? 설명에서는 정말 쓰레드가 할일이 없어서 바로 처리해줄 상황을 생각해서 넣어주신거라고 하셨는데 이 부분을 없애도 args.Completed 이벤트 발생 시 문제 없이 OnAcceptCompleted 를 불러오던데 굳이 넣어주신건 성능 개선차원인가요??
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Servercore와 DummyClient의 동시실행
안녕하세요! 매번 정성스런 답변 감사드립니다. 조금 뜬금없는 질문일 수 있지만... Server core와 Dummy Client를 동시에 실행시키는 강의의 코딩도 일종의 멀티쓰레드 환경으로 볼 수 있는 건가요..?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
웹서버와 게임서버의 활용에 관하여 질문이 있습니다.
좋은 강의 만들어주셔서 감사합니다. 정말 잘 가르쳐주셔서 너무 익혀나가고 있습니다. 다름이 아니라 혹시 웹서버와 게임서버의 활용에 관하여 질문이 개인적인 질문이 있는데 어디에 문의를 드려야 할지 모르겠어서 여기로 질문드립니다... 친구들과 같이 진행중인 프로젝트가 있는데 서버를 처음 다루다보니 AWS를 활용한 웹서버 + 클라이언트 구조로 활용하여 게임을 개발하려 하였습니다. 그런데 이제 OT에서 웹서버와 게임서버의 활용법을 얘기하셔서 저희 게임의 기획에 맞게 게임서버를 활용하기로 하였습니다. 다만, 웹서버와 게임서버를 병행하여 랭킹시스템, 유저정보 등은 웹서버를 활용하여 매치메이킹을 해주는 등에 활용하고 실제 게임이 매치되어 진행하는 동안에는 게임서버를 사용하는 것으로 구상중에 있습니다. 이제 로딩시 버전체크 등 파일 확인에도 웹 서버를 활용하면 괜찮을거 같아서 이렇게 진행을 하고 싶은데 하나의 게임 안에서 서버를 교체하여 매치를 진행한다는 것이 가능한 것인지가 궁금합니다. 저희가 아직 학생신분을 가진 상태라서 서로가 공부목적으로 진행하는 프로젝트이다 보니 웹서버에 관심을 가지고 있는 친구가 있어 포기할 수는 없는 상태인데 이게 이중연결이 진행이 되는 것인지 아니면 웹서버의 연결을 끊고 게임서버로 다시 연결시켜주는게 괜찮은 방식인가 싶습니다... 강의와는 무관한 질문 정말 죄송합니다 ㅠㅠ