월 17,600원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
테스트 메모리 릭킹 관련 질문
아래와 같은 테스트를 진행했고 이는 강의코드에도 유사하게 발생할 것으로 보입니다. 서버 컨텐츠단에서 패킷 모아 보내기 기능까지 구현500개의 더미 클라이언트가 S_Chat 을 송신서버는 비주얼 스튜디오에서 디버그모드로 구동더미클라이언트는 exe모드로 실행과 종료를 반복 이때 클라이언트의 connect, disconnect가 잦아지면서 서버의 메모리 점유율이 내려가지 않는 현상이 궁금해서 그러는 것이지, 고쳐달라고 떼쓰는게 아닙니다. 이런 현상은 강의 코드에서도 발생할 것으로 보이는데요. 혹시 알고 계신 이유가있다면 그것만 말씀해주시면 됩니다.
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
테스트 중 메모리 릭킹 현상 질문
테스트를 하다 릭킹(leaking) 현상이 생기는게 궁금해서 여쭙습니다.테스트 과정서버 컨텐츠단에서 0.15~0.25초 단위로 패킷을 모아보내는 기능까지 구현더미 클라이언트에서 500명이 C_Chat 패킷을 보내도록 구현서버만 Visual Studio의 디버그 모드로 실행 (메모리 진단을 위해)클라이언트는 빌드된 exe파일로 접속클라이언트만 반복적으로 종료하고 다시 실행이때 서버쪽 메모리 점유율이 올라가기만 합니다.Disconnect() 가 분명히 불리고 소캣을 Clean(), Shutdown()을 하는데 (심지어 Dispose()도 넣음 다 돌아가는거 확인)서버 메모리 점유율이 260메가 막 그러네요, 아무리 오래 두고 봐도 CG가 정리할 생각을 안해요 ㅠㅠ다 깔끔하게 정리할 욕심은 없습니다. 다만 릭킹은 안좋아보여서요.이거 이유가 있을까요? 참고로 리스너쪽 대기 큐 150 이상으로 설정해야 테스트가 잘됐습니다, (강의시 backlog 인자)
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
경합조건과 임계영역의 차이
안녕하세요. Interlocked 과목 중 경합 조건Race Condition에 대한 수업 잘 들었습니다.과거 네트워크와 운영체제 시간에 배웠던 임계 영역과 경합 조건에 대한 개념이 헷갈려서 질문 드리고 싶습니다.말씀해주셨던 다수의 쓰레드들이 하나의 데이터 혹은 그러한 영역에 접근하고자 할 때 생기는 문제를 저는 경합 조건이라고 이해했는데요.이 개념이 혹시 임계 영역을 제가 잘 못 이해하고 있는지, 혹은 경합 조건에 대해 제대로 이해하고 있는지 궁금합니다.또 선생님께서 생각하시는 임계영역과 경합조건의 차이는 어떠한 것인지도 궁금합니다.
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
펙토리 함수가 꼭 필요한건가요? 그냥 세션으로 받으면 안되요?
public void Connect(IPEndPoint endPoint, Session session) // 사용하는 부분//connector.Connect(serverEndPoint, () => { return new GameSession(); }); GameSession gameSession = new GameSession(); connector.Connect(serverEndPoint, gameSession);Func 형 말고 그냥 Session을 참조로 받아서 하면 안되나요? 코드가 돌긴 하던데..
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Disconnect 순서 문제질문드리고싶습니다!
가끔 결과가 위처럼 나오는데 이 문제는 서버단에서 RegisterRecv를 해주는 도중에 클라에서 send를 다해주고 Disconnect 해버려서 발생하는 문제인가요??위에 Seesion.cs : lin116은 OnRecvCompleted함수에서 OnRecv를 해주고 다시 RegisterRecv()<< 이 함수를 호출하는 줄입니다.
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
강의에서 쓰레드 생성되는게 제가 이해한게 맞을까요?
다만 Listener의 Init 부분에서 위 사진의 코드가 register개 만큼 쓰레드를 생성한다고 보면 맞을까요? 그리고 C++에서는 여러개의 Worker Thread가 GetQueuedCompletionStatus 로 이벤트 분기에 따라 send, recv, accept, connect 등을 처리해줬는데, 이 코드는 Accept만 멀티쓰레드로 처리하고 Send, Recv는 싱글쓰레드로 처리되는건가요?
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
서버엔진 수요에 관해서 질문드립니다.
대학 게임학과에 재학 중인 학생입니다.교수님과 게임서버프로그래밍에 대해 상담을 나누는 도중교수님께서 MMORPG를 포함한 대부분의 프로젝트에서 서버를 직접 만드는 경우는 거의 없고언리얼 데디케이트, 포톤, 프라우드넷 같은 이미 만들어진 모델이나 서버엔진을사용한다고 말씀하셨는데 정말인가요?보통 반대로 대부분의 프로젝트가 게임에 맞춰 서버엔진을 제작하는 줄 알았는데제가 알던 상식과는 너무 달라서 질문드립니다.
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
lock 에 대해서 질문드립니다
Session 의 Send에서 lock 을 걸고RegisterSend 로 진입 -> SendAsync 의 pending 이 false라면 바로 같은 스레드에서 OnSendCompleted 진입그런데 OnSendCompleted 도 처음에 lock 을 걸어야하는데 위 같은 경우 Send 에서 걸었던 lock 이 아직 풀리기 전에 호출스택이 OnSendCompleted 까지 쌓이는데OnSendCompleted 에서 lock 안으로 진입할수 있는 이유는 같은 쓰레드 여서 인가요?
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
바이트 오더 정렬 안 해도 상관없나요?
패킷 코드를 봐도 딱히 호스트,네트워크 간의 바이트 정렬은 하지 않던데내부에서 간단히 테스트할 꺼라 처리를 하지 않으신 건가요? 아니면 다른 방법으로 하셨는데 제가 못 찾는 걸까요
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
null체크후 clientSession.Room을 참조하면 Push 할때 null이 넘어갈수 있는거 아닌가요?
안녕하세요. 강의 열심히 보고 있습니다. ^^JobQueue #1 강의중 19분51초에서..멀티스레드 환경에서14줄에서 null 체크를 하고접속이 해제된다면17줄에 room을 넣을 때null이 반환되지 않을까요?? 검색해봐도 해당 내용은 없는거 같아서 질문 드립니다.
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
공간이 부족해서 기존 청크를 날리는 건 괜찮을 걸까요?
Queue<byte[]> _sendQueue = new Queue<byte[]>();_sendQueue.Enqueue(sendBuff);이렇게 sendBuff를 넣어놔서 누군가 참조하고 있을 수 있기 때문에 밀어서 사용하지 않은 건데 if (CurrentBuffer.Value.FreeSize < reserveSize)CurrentBuffer.Value = new SendBuffer(ChunkSize); 이렇게 기존 청크 날리고 새로운 아이로 교체를 하면 밀어서 사용하지 않는 의미가 퇴색되는 거 아닌가요? 꽉 차서 기존 청크를 날릴 때 즈음에는 참조하고 있는 애가 없어질 확률이 높기 때문에 꽉 차서 날리는 건 괜찮은 걸까요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
안에 있다는 말이 엔진단 안에 있다는 말씀이신가요?
recvBuffer는 안에 있어서 Session마다 고유한 recvBuffer를 갖고 있다고 하실 때 안에 있다는 말은 ServerCore안 즉 엔진단 안에 있다는 말씀이신가요? 설명하실 때 안에 있다 언급하실 떄 마다 엔진단 안이라고 이해하고 있었는데 맞게 이해하고 있는 건가요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
pending이 true면 어떨 때 args.Completed.Invoke()가 실행되는 건가요??
public void Init(IPEndPoint endPoint) { // 문지기(가 들고있는 휴대폰) _listenSocket = new Socket(endPoint.AddressFamily, SocketType.Stream, ProtocolType.Tcp); // TCP로 할 때 설정 // 문지기 교육 _listenSocket.Bind(endPoint); // 식당 주소와 후문인지 정문인지 기입을 해준 것 // 영업 시작 // backlog : 최대 대기수 _listenSocket.Listen(10); SocketAsyncEventArgs args = new SocketAsyncEventArgs(); args.Completed += new EventHandler<SocketAsyncEventArgs>(OnAcceptCompleted); RegisterAccept(args); } void RegisterAccept(SocketAsyncEventArgs args) { bool pending = _listenSocket.AcceptAsync(args); if (pending == false) // 운 좋게 바로 클라이언트가 접속했을 경우 OnAcceptCompleted(null, args); } void OnAcceptCompleted(object sender, SocketAsyncEventArgs args) { }클라이언트가 접속을 하면 pending이 false가 되어서 OnAcceptCompleted가 직접 실행이 되지만 클라이언트가 접속을 안해서 pending이 true인 경우는 직접 실행이 안되고, args.Completed.Invoke()일 때 실행이 되는 건데 진짜로 완료 되었을 때란 어떨 때라고 할 수 있을까요?
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
JobQueue 사용에 대한 질문
우선 저는 단순히 Lock 만 사용하면 무수한 경합으로 인해 성능적으로 손해를 볼 수 있어 Job Queue 를 사용하는 것으로 이해를 했습니다.그래서 이것저것 연습하면서 Job Queue 를 계속 사용하고 있는데 도중에 몇몇 의문이 생기어 질문을 드리게 되었습니다. Job Queue 를 사용하다보면 Job Queue 내에 또 다른 Job Queue 를 사용해야하는 상황이 발생하는데 이 부분은 문제가 되지 않을까요?아래는 예시 코드입니다.public void Function() { MatchingManager.Instance.Push(() => { ... User.Party.Push(() => { ... }); }); } Lock 처럼 사용하면 된다 라는 생각은 옳은 것인가요? 아니면 Lock 과는 달리 Job Queue 사용 시 주의 할 부분이 있을까요? 항상 양질의 강의를 제공해주셔서 감사드립니다.
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
맥북에서 비쥬얼 스튜디오 사용중인데 아래와 같은 결과가 나타나지 않습니다. 무슨 문제일까요?
이건 샘 화면이고이건 제 맥북 vs 화면입니다.Hello Thread! 다섯번이 결과로 안나오네요 ㅠㅠ 챗지피티에 물어봤더니 아래와 같이 답을 줍니다..NET ThreadPool은 개발자가 작업을 실행할 스레드 풀을 할당하여 여러 작업을 동시에 실행할 수 있도록 하는 메커니즘입니다. 그러나 Mac의 Visual Studio에서 ThreadPool 기능 문제에 대한 보고가 있었습니다. 이 문제에 대한 한 가지 잠재적인 이유는 Windows와 macOS 간의 기본 운영 체제 및 런타임 환경의 차이 때문일 수 있습니다. 또 다른 가능성은 Visual Studio의 두 버전 간에 ThreadPool 기능 구현의 차이일 수 있습니다.Mac의 Visual Studio에서 ThreadPool에 문제가 발생하는 경우 문제를 해결할 수 있는 업데이트 또는 패치를 확인하고 문제를 일으킬 수 있는 잠재적인 문제에 대한 코드를 검토하는 것이 좋습니다. 다른 플랫폼에서 더 나은 성능과 안정성을 제공할 수 있는 async/await 또는 TPL(Task Parallel Library) 사용과 같은 동시성에 대한 대체 접근 방식을 탐색하는 것도 가능합니다.
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
메모리가 늘어나는 것과 sendbuffer 관계
안녕하세요! 강사님. 클라이언트를 500명으로 늘렸을 때 말로 설명해주신 부분에서 이해는 가는데, 일부분이 정확하게는 이해가 가지 않는 부분이 있습니다. 작업이 밀려버리면 스레드풀에서 보낸 스레드가 돌아오지 않으니 새로운 스레드를 만들기때문에 메모리가 점점 찬다 -> 스레드가 패킷을 async하게 recv한 다음 jobqueue에 push를 할 때, push 하기위해 lock이 있으니 해당영역에서 병목현상이 발생하고, 그로인해 blocking된 스레드가 오지 않으니 스레드풀에서 새 recv가 오면 스레드 재사용이 아니라 새 스레드를 할당하기 때문에 스레드는 각 스레드별로 stack을 가지고 있기 때문에 이런 스레드별로 가지고있는 용량이 계속 증가하는거라서 메모리가 늘어난다. 라고 이해를 했었습니다. 그런데 나중에 다시 말씀해 주셨을 때,일이 계속 밀리면, 스레드풀에서 스레드가 돌아오지 않으니 새로운 스레드를 만들고, sendbuffer에서 큰 단위의 버퍼에서 짤라서 사용하는걸로 구현했기 때문에 메모리가 계속 늘어난다. 라고 하셨는데, sendbuffer는 여러 스레드가 큰 버퍼에서 짤라서 각자 쓰는 것으로 이해를 했었어서 여러 스레드가 써도 큰 버퍼는 그대로고 얼마나 sendbuffer를 사용하는 횟수가 많아지냐. 가 달라지는거라고 생각이 들었는데,,, 그게 아닌가요? sendbuffer에서 큰 단위의 버퍼에서 짤라서 사용하는 것이 메모리 증가에 무슨 영향이 있는지 잘 이해가 되지 않습니다.
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
반사된 메세지 recv하였을 때의 순서 동일한 이유
안녕하세요, 강사님! GameRoom에서 client -> server로 보낸 메세지를 다른 client들에게 broadcasting을 하는데, 그래서 출력 결과가 10개씩 나오는 이유가10개의 클라이언트들이 보낸걸 다시 반환하는것이기 때문에.즉, 반사가 10개씩 나오는거고, 근데 클라이언트 console창이 하나로만 되어있다보니 10개의 클라이언트가 받은 반사메세지가 한번에 출력되어 10개씩 출력되는 것이라고 이해를 했습니다. 그런데 각 session이 어떤 순서로 반사를 받는지 궁금하여 client의 serversession에도 sessionid를 부여하고 테스트로 출력을 해 본 결과 아래와 같았습니다.session이 send 를 하는 것은 async로 구현하였기 때문에 비동기방식인데, 저렇게 규칙적으로 받아오더라구요.(4 2 3 1 5 0 6 7 8 9 ...순서) Program.Room.Enter(this); 를 한 순서대로 GameRoom의 _sessions 리스트에 추가가되니 Broadcast 때 리스트를 foreach하니까 리스트에 추가된 순서대로 오는 것 같다고 생각이 드는데, 사실 네트워크 상태에 따라서 패킷이 라우터에 경로가 달라지니 각기 다른 순서로 올 수도 있고(이건 그렇게 부하가 큰편은 아니니 그래도 해당 원인은 무시한다고 쳐도), 멀티스레드이기도 하고 thread context switching 으로 인해 스레드간 순서가 마구마구 뒤바뀔거라 예상을 했지만, 저렇게 규칙적으로 나오는 이유가 무엇인지 궁금합니다. 그리고 새로 실행 시 마다 저 규칙이 변경이 되는데, 그 이유는 사실Listener에서 Onconnected를 하여 Program.Room.Enter(this); 안에 들어가는 순서가 멀티스레딩이라서 다르게 들어가기 때문이라고 이해를 했습니다. 그렇다면 멀티스레딩으로 인한 순서 뒤바뀜이 있다는 증거이고 사실 listener가 받는 것 또 한 GameRoom에서 broadcasting하는것과 비슷하게 lock을 걸고 순서대로 session list에 추가하고 즉, 순차적으로 여기서 리스트 순서대로 보내도 순서뒤바뀜이 일어나서 GameRoom에서의 List에 쌓이는 순서도 바뀌는거라고 생각이 들거든요. 그러면 SendForEach에서 ServerSession리스트를 보낼 땐 멀티스레드로 인해서 순서가 뒤바뀌는데, Server의 GameRoom에서 ClientSession 리스트를 뽑아 send할 땐 순서가 유지되어 send보내지는 이유는 뭔가요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Name이 한번 오면 초기화되는 이유
안녕하세요, string serialize를 하여 read, write 코드를 추가한 이후 확인해보려 코드를 실행해보았는데, 처음엔 name이 잘 나오지만 client에서 5번 연속으로 보냈을 때 name이 null인건지 나오질 않아 확인해보니, 아래와같이 처음 이후에는 name이 null이 되는 것 같습니다. 해당 이유를 찾기가 힘들어서 왜이러는지 이해가 되질 않습니다.
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
string write할 시에 Array.Copy한 이유
안녕하세요, string serialization을 할 때 Array.Copy를 한 이유에 대해서 다른 long, ushort등과같은 데이터들은 TryWriteBytes()메서드를 사용하여 바로 dest인 buffer에 바이트를 써 주는 메서드가 구현되어있지만, string을 인자로 받는 메서드와 byte배열을 받는 메서드는 없어서 GetBytes한 이후에 Array.Copy로 buffer배열에 직접 복사한것같은데, 맞을까요?그럼 더 궁금한건, TryWriteBytes는 ValueType만 바이트로변환해서 dest에 쓸 수 있도록하는 메서드인거라고 이해하면 될까요? string, byte[]등과같은 reference type을 인자로 받는 메서드는 구현이 안되어있는 이유를 혹시 아시는지요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
강사님처럼 여러 프로세스 디버깅하는 방법
안녕하세요, Serialization#2 강의를 따라 치는 도중 실행을 하면 recv할 때 playerid가 0으로 나와 디버깅을 하려고 했지만, 디버깅시에OnConnected : [fe80::c104:b687:d2b9:82d8%14]:7777OnDisconnected : [fe80::c104:b687:d2b9:82d8%14]:7777Unhandled exception. System.ObjectDisposedException: Cannot access a disposed object.Object name: 'System.Net.Sockets.Socket'.at System.Net.Sockets.Socket.SendAsync(SocketAsyncEventArgs e, CancellationToken cancellationToken)at System.Net.Sockets.Socket.SendAsync(SocketAsyncEventArgs e)at ServerCore.Session.RegisterSend() in C:\Users\jiw72\CsharpServer\MMORPG\Server\ServerCore\Session.cs:line 124at ServerCore.Session.Send(ArraySegment`1 sendBuff) in C:\Users\jiw72\CsharpServer\MMORPG\Server\ServerCore\Session.cs:line 97at DummyClient.ServerSession.OnConnected(EndPoint endPoint) in C:\Users\jiw72\CsharpServer\MMORPG\Server\DummyClient\ServerSession.cs:line 98at ServerCore.Connector.OnConnenctCompleted(Object sender, SocketAsyncEventArgs args) in C:\Users\jiw72\CsharpServer\MMORPG\Server\ServerCore\Connector.cs:line 42at System.Net.Sockets.SocketAsyncEventArgs.OnCompleted(SocketAsyncEventArgs e)at System.Net.Sockets.SocketAsyncEventArgs.ExecutionCallback(Object state)at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)--- End of stack trace from previous location where exception was thrown ---at System.Threading.ExecutionContext.RunInternal(ExecutionContext executionContext, ContextCallback callback, Object state)at System.Threading.ExecutionContext.Run(ExecutionContext executionContext, ContextCallback callback, Object state)at System.Net.Sockets.SocketAsyncEventArgs.<>c.<.cctor>b__177_0(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)at System.Threading.ThreadPoolBoundHandleOverlapped.CompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* nativeOverlapped)at System.Threading._IOCompletionCallback.PerformIOCompletionCallback(UInt32 errorCode, UInt32 numBytes, NativeOverlapped* pNativeOverlapped)C:\Users\jiw72\CsharpServer\MMORPG\Server\DummyClient\bin\Debug\netcoreapp3.1\DummyClient.exe(프로세스 25828개)이(가) 종 이렇게 중간에 예외처리가되어 종료가됩니다. 뭔가 프로세스 단계별 실행을 해보았을 때, dummyclient를 클릭하고 디버깅하면 dummyclient만 디버깅되고 server를 클릭하고 디버깅하면 server만 디버깅되더라구요.그래서 여러 시작 프로젝트를 한것처럼 디버깅도 여러 프로젝트를 동시에 할 수 있도록 하는 방법은 없는건가요?