월 17,600원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
사진처럼 클라이언트는 5번 보내는데, 서버는 6번 로그를 찍습니다. 왜 그런지 알 수 있을까요?
(사진)
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
하드웨어 최적화 질문
1) 첫번째 예제에서 r1,r2를 CPU가 최적화 하는 방식이 궁금해서 각 쓰레드별로 얼만큼 CPU가 순서를 바꿨는지를 세어 봤습니다. 세어 보니까 쓰레드 별 횟수 차이가 되게 많이 났습니다. 이게 CPU가 실행중에 옆에 쓰레드를 보고 "아 첫 쓰레드에서 x값을 쓰네 나는 조심해야겠다"하고 생각해서 두번째 쓰레드는 코드의 순서를 더 바꾼건가요?? 2) Thread.MemoryBarrier에서 Thread 클래스에 각 thread들을 관리할 수 있는 기능이 있는거 같은데, c# 쓰레드 클래스 안에 각 instance들을 자료구조로 관리하고 있는건가요??
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
서버 보안 관련 질문 드립니다!
안녕하세요, 항상 강의 정말 재미있게 수강하고 있습니다! 서버의 구조가 어떤지, 어떻게 동작하는지 전반적으로 알 수 있게 되어서 루키스님께 정말 감사할 따름입니다. 강의를 듣고나서 추가적으로 궁금한 점이 생겨서 질문 드립니다! 강의에서 만든 TCP 서버(게임 서버)와 클라이언트가 패킷을 주고 받을 때 현업에서는 어떻게 보안 처리를 하는지 궁금합니다. 현재 서버 구조는 패킷 전체를 암호화한다면 패킷 헤더에 있는 내용을 읽을 수 없어서 ReadBuffer에서 몇 바이트를 읽어와야 하는지 알 수 없게 될텐데 게임 서버 구조가 이러한 구조라면 헤더는 빼고 암호화를 하여 보안처리를 해야 복호화 후에 데이터를 읽어올 수 있을 것 같아서요. 아니면 다른 방법을 사용하는 것인지 궁금합니다!
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
AcceptAsync, ReceiveAsync문의드립니다.
1. AcceptAsync 재귀 - 백로그 큐의 크기가 있다고 해도 초기 오픈한 게임의 경우 사용자가 지속적으로 들어올것 같은데,이 때는 AcceptAsync 호출 시 계속 pending에서 false가 나올것 같은데 이 때는 코드적으로 조치를 취해야 겠죠? 2. ReceiveAsync - 사용자가 지속적으로 데이터를 보낼 경우 지속적으로 수신 버퍼에 데이터가 있을 수 있기 때문에 pending false 로 인한 재귀에 빠질 수 있을것 같은데 이 때도 조치를 취해야 하나요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
20분 30초 ConnectionReset
안녕하세요20분 30초에서 클라이언트의 연결을 끊었을 때 서버 콘솔에서 ConnectionReset 이라는 로그가 나왔는데, 이거는 어디서 출력하는 건가요? 저도 똑같이 해봤는데 ConnectionReset 이라는 로그가 안나오네요 ㅜㅜ
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
GenPackets.cs 에 Read 함수 부분이 이상합니다
GenPacket.bat 파일을 실행하여 복사된 GenPackets.cs에서 해당 스크린샷 부분에 오류가 뜹니다 이게 변수 level의 자료형이 달라서 나오는 오류라고 파악하고 위의 스크린샷에 해당하는 부분이 문제라고 생각하여 이런식으로 바꾸어 실행하니 이런식으로 오류없이 제대로 복사가 되었습니다 그런데 강의 영상에서는 이런식으로 수정한 부분이 없이도 오류가 안뜨던데 혹시 다른부분을 놓친것인데 제가 잘못 수정한것일까요? 그리고 혹시 몰라서 수정하기 전의 코드로 다시 돌려서 다시 실행하니 이번에는 오류가 안뜨고 제대로 복사가 되었습니다 단순 컴퓨터가 오류인걸까요...
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
WriteUnlock() 질문드립니다.
WriteUnlock() 코드를 보면은 Interlocked 를 사용하셔서 _flag를 EMPTY_FLAG로 변경하시는데, 이부분은 _flag = EMPTY_FLAG; 로 해도 되지 않나요? 대입은 원자적인 연산으로 처리되는 걸로 알고 있어서 요
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
SocketAsyncEventArgs 의 EventHandler와 threadPool
SocketAsyncEventArgs의 Completed eventHandler가 소켓의 AcceptAsync함수가 이후에 완료되면 (pending == true) threadPool에서 하나의 작업쓰레드를 가져와서 해당 이벤트를 처리하는것 같습니다. 그래서 서버를 돌리다가 중단을 하면 작업쓰레드가 많이 생성되는것이 보입니다. 그렇게 생성되는 작업쓰레드는 Session을 생성하고 거의 곧바로 완료가 되어서인지 중단을 해보면 쓰레드가 실행중인 코드를 찾을수가 없다고 나옵니다 (아마 해당 쓰레드는 제가 작성한 코드를 실행하고 있는것이 아니라 디버깅을 할 수 없는 부분의 더 낮은(?) 부분의 일을 하고 있거나 이미 자신의 일을 다 하고 다시 threadPool로 들어가고 있기 때문이라고 생각했습니다.) 어찌되었든 소켓통신이 발생될때마다 쓰레드가 마구잡이로 동원되는것이 맘에 들지 않아서 socket 에 관한 async 함수의 완료 이벤트만 담당하여 수행하는 쓰레드를 만들어 따로 관리를 하려고 했습니다. (궁극적인 목표는 서버나 클라이언트에서 코어 *2의 쓰레드를 미리 만들어놓고 해당쓰레드 이외의 다른 쓰레드는 생성하지 않는 것입니다.) 그러나 기존의 방법으로는 pending이 일어나고 나중에 이벤트가 호출이 될 때 호출되는 쓰레드를 미리 정하는 방법이 있는지 잘 모르겠습니다. 다른방법이 있는지 고민하고있는데 적절한 답이 떠오르지 않아 이렇게 질문드립니다. 감사합니다.
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Task 순서 질문
안녕하세요. 아래 코드처럼 Task 안에 while 대신 i를 찍어보게 했는데 왜 i가 0~3까지 나오지 않고 전부 4로 찍히는지 제가 이해하고 있는게 맞는지 궁금합니다. Task.Start() 함수는 TaskScheduler에 예약을 시키는 함수이기 때문에 for문을 돌면서 바로 실행시키지 않는데요. 실행순서가 오로지 스케쥴러에게 의존적이기 때문에 예측할 수 없고, 따라서 이미지와 같이 실행할 때마다 다르게 나옵니다. i가 4가된 이유는 for문을 4번 다 돈 후 어느 특정 시점에 Task(일감)이 실행이 되기 때문에, i=4로 찍히는 것입니다. 디버그 모드에서 천천히 한줄한줄 실행했을 경우 i가 4가 아닌 경우도 출력이 되던데, 그냥 실행시키는 경우에도 진짜 운좋으면 i가 4가 아닌 경우도 나올수가 있을까요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
C# 비동기 처리 방식 질문드립니다.
C++은 IOCP모델에서 쓰레드를 직접 생성해서 IOCP의 쓰레드풀을 통해 관리되고, 비동기 함수가 완료되면 쓰레드풀에 있던 대기상태의 쓰레드가 실행상태로 바뀌면서 작업을 처리하는 방식이라면 C#은 직접 쓰레드를 생성하지 않을뿐이지 비동기 함수를 이용하면 알아서 쓰레드풀에서 쓰레드를 생성하고 관리하는 것 같던데 비동기 함수 사용하는 순간 C++ IOCP처럼 사용한다고 생각하면 될까요? 아직 뒷강의를 보진 않았지만 위 말이 맞다면 Send,Recv 비동기 함수도 AcceptAsync함수처럼 처리하면 되는지 궁금합니다. +질문으로.. C++을 처음 공부할 때 예외처리문을 멀리하고, 예외상황이 발생하면 차라리 Crash를 터트리고 문제상황을 고치는게 좋다고 배웠는데 C#은 문제가 발생하면 항상 예외를 던지더라구요. C#을 쓸땐 try~catch같은 예외처리문을 항상 사용하는게 좋은 습관이 될까요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
OnAcceptCompleted 질문입니다!
양질의 강의 정말 잘 보고있습니다!제가 이해하고 있는게 맞는지 질문드립니다. 1. _listenSocket.AcceptAsync(args); 이함수를 실행하면 비동기적으로 계속해서 연결요청이 있는지 확인 2. 연결 요청이 왔을시 내부에서 누군가가(닷넷)args.Completed.Invoke(sender, args) 실행 3. 등록했던 이벤트 OnAcceptCompleted 가실행됨이런흐름이 맞을까요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
NullReference 오류가 뜹니다
채팅 테스트 #2 를 보는 도중 첫 테스트에서 ClientSession부분의 OnRecvPaacket쪽에서 nullReference의 오류가 뜨는데 왜 이러는지 모르겠습니다...
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Listener 관련 질문
강의 내 1:45초쯤 더 많은 손님을 받을수 있도록 Listener에 for문을 추가하였습니다. RegisterAccept -> (socket.AcceptAsync) -> OnAcceptCompleted -> RegisterAccept로 이어지는 loop가 10개 생성되었다고 이해했습니다. 그렇다면 하나의 ListenSocket에 10개의 loop가 묶여있는 상태에서 client로부터 온 소켓들이 어떻게 하나씩 배치될수 있나요? 다른 loop에 같은 소켓이 배치될수도 있을것 같은데 아무리 생각해도 이 부분이 이해가 잘 안가서 질문드립니다. 강의 잘 수강하고 있습니다. 감사합니다.
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
왜 오류 발생하는지 모르겠음
밑에 보면 skill.Read(s, ref count)에서 count의 타입은 ushort이고, 위에 SkillInfo의 Read의 프로퍼티에 있 는 count의 타입도 또한, ushort인데, 왜 다음과 같은 오류가 발생하는지 모르겠습니다
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
실행 오류
오류를 어떻게 고치는지 모르겠어요. Server 뭘 깔라고 하는데 굳이 깔아야할까요?? 다른 방법이 없을까요..
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Knight를 Send할 때 8 바이트가 아닌 버퍼의 전체 크기인 409600바이트 만큼합니다.
ArraySegment<byte> openSegment = SendBufferHelper.Open(4096); byte[] buffer = BitConverter.GetBytes(knight.hp); Console.WriteLine(buffer.Length); byte[] buffer2 = BitConverter.GetBytes(knight.attack); Console.WriteLine(buffer2.Length); Array.Copy(buffer, 0, openSegment.Array, openSegment.Offset, buffer.Length); Array.Copy(buffer2, 0, openSegment.Array, openSegment.Offset + buffer.Length, buffer2.Length); ArraySegment<byte> sendBuff = SendBufferHelper.Close(buffer.Length + buffer2.Length); Send(sendBuff); 이 코드를 이용해 Send를 할 때 강의를 보며 8바이트만 보내게 되지만 서버 Listening... OnConnected : [fe80::2196:d828:3293:b5c5%4]:50464 4 4 [From Client] Hello World! 0 [From Client] Hello World! 1Hello World! 2Hello World! 3Hello World! 4 Transferred bytes : 409600 OnDisconnected : [fe80::2196:d828:3293:b5c5%4]:50464 더미 클라이언트 OnConnected : [fe80::2196:d828:3293:b5c5%4]:7777 Transferred bytes : 14 Transferred bytes : 14 Transferred bytes : 14 Transferred bytes : 14 Transferred bytes : 14 [From Server] d [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] [From Server] OnDisconnected : [fe80::2196:d828:3293:b5c5%4]:7777 이런 식으로 8바이트만보내는게아닌 buffer를 모두 보내버리는데 문제점을 못찾겠습니다. Sendbuffer 코드 using System; using System.Collections.Generic; using System.Linq; using System.Text; using System.Threading.Tasks; using System.Threading; namespace ServerCore { public class SendBufferHelper { public static ThreadLocal<SendBuffer> CurretBuffer = new ThreadLocal<SendBuffer>(()=> { return null; }); public static int ChunkSize { get; set; } = 4096 * 100; public static ArraySegment<byte> Open(int reserverSize) { if (CurretBuffer.Value == null) CurretBuffer.Value = new SendBuffer(ChunkSize); if (CurretBuffer.Value.FreeSize < reserverSize) CurretBuffer.Value = new SendBuffer(ChunkSize); return CurretBuffer.Value.Open(reserverSize); } public static ArraySegment<byte> Close(int usedSize) { return CurretBuffer.Value.Close(usedSize); } } public class SendBuffer { byte[] _buffer; int _usedSize = 0; // 사용한 버퍼 public int FreeSize { get { return _buffer.Length - _usedSize; } } public SendBuffer(int chunckSize) { _buffer = new byte[chunckSize]; } public ArraySegment<byte> Open(int reserveSize) { if (reserveSize > FreeSize) return null; return new ArraySegment<byte>(_buffer, _usedSize, reserveSize); } / public ArraySegment<byte> Close(int usedSize) { ArraySegment<byte> segment = new ArraySegment<byte>(_buffer, _usedSize, usedSize); _usedSize += usedSize; return segment; } } }
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Task의 LongRunning
Task에 LongRunning을 주게되면 스레드풀에서 작업을 하지않는다고하는데, 그럼 Task에 LongRunning을 주면 스레드풀에 있는 스레드가 아니라 별도로 스레드를 하나 만들어서 처리하는건가요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
초록줄에러...
ㅇ이런에러는 어떻게 해결하나요??
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
1
1
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
OnAcceptHandler 관련 질문
OnAcceptHandler가 static으로 정의되어 있는데 이 때 안에 있는 session 인스턴스도 1개만 성생이 되나요? 만약에 아닐 경우 각각의 쓰레드가 OnAcceptHandler를 호출면서 각각의 session 인스턴스를 가지고 있을텐데 굳이 session 안에서 동시성 문제를 해결하기 위해 lock을 해줘야 되나요?