월 17,600원
5개월 할부 시다른 수강생들이 자주 물어보는 질문이 궁금하신가요?
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Interlocked를 사용하지 않고 원자성을 만드는 방법
C#에서 어떻게 할 수 있을까요?
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
lock 키워드
lock()에 들어가는 객체 변수의 의미가 궁금합니다. 아무거나 넣어줘도 무관하다면 왜 인자를 받는지 궁금합니다.
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
JobTimer에 관하여 질문있습니다.
안녕하세요 JobTimer강의를 듣던 중 궁금한 점이 생겨 질문드리게되었습니다. 질문1 ) JobTimer의 CompareTo 메서드를 통해 오름차순으로 정렬해야 하는 것 아닌가요?(execTick이 작은것 부터) other,execTick - execTick 을 리턴하면 내림차순으로 정렬이 되지 않나요? 테스트해보니 5,4,3,2,1 순으로 나오네요... 질문2) JobTimer의 _pq(PriorityQueue)에 Push나 Pop등은 MainThread에서 단일로 작업하지 않나요? 그럼에도 lock이 필요한 이유가 무엇인가요? 읽어주셔서 감사합니다.
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
job queue 흐름에 관하여 질문있습니다
안녕하세요 항상 좋은 강의 잘 듣고 있습니다. jobqueue에 대해서 궁금한 점이 생겨 질문드리게 되었습니다. 질문1) 예를 들어 ABCDE쓰레드가 거의 동시에 C_Chat 패킷을 핸들링할 경우, C_ChatHandler 가 아래와 같고("패킷을 받았습니다" 메세지 전송 추가) Push의 lock에 접근한 순서가 문자 순서대로 A가 1번 B가 2번...이라면 A쓰레드는 Flush를 수행한 후 클라이언트에게 "패킷을 받았습니다를" 보내주고 나머지 BCDE쓰레드들은 Flush를 수행하지 않고 큐에 넣기만 하고 "패킷을 받았습니다"라는 메세지를 보내게 되는 게 맞나요? 질문2) 위 내용이 맞다면 A쓰레드는 단지 1등으로 Push의 lock에 접근했다는 이유로 Flush(요리)를 수행하고, 응답("패킷을 받았습니다"라는 메시지 Send // Push로 등록한 action이 아닌 Push 이후의 흐름들)을 Flush수행 시간만큼 늦게 보내게 되는 것인데 뭔가 불합리?하다고 느껴집니다. 이런 정책을 많이 사용하나요?
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
서버 로그 출력
서버와 클라를 실행했을 때 500명 모두가 OnConnected가 뜨지 않고 약 200 ~ 300 사이에서 서버 로그출력이 멈춥니다. (어쩌다가 한번씩은 500까지 찍힙니다.) 왜 그런것인가요? 어떻게 해결해야하나요? 리스너의 백로그를 늘려도 마찬가지네요...
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
제 visual studio에서는 number++의 원자성이 보존되는거같은데 맞나요...?
제 디스어셈블리에서는 number++; 가 선생님 강의와 다르게 나옵니다. number의 주소값에 접근해서 그 값을 바로 1 증가시켜주는 것 같은데 원자성이 보존되는게 아닌가? 라고 생각해봤지만 결과는 0이 안나오더라구요. inc dword ptr ds:[0F04424h] 이 줄이 number의 주소값에 접근해서 그 값을 바로 1 증가시켜주는게 아닌가요?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
메모리 베리어 개념이 살짝 헷갈려서 질문드립니다!
2번째 예제에서 메모리 베리어가 없으면 1) 스레드 A가 실행된다. 2) _answer = 123; 보다 _complete = true;가 먼저 실행되는 경우가 생긴다.(코드 재배치) 3) _answer = 123;이 실행되기 전에 스레드 B가 실행된다. 4) _complete = ture이므로 _answer = 0이 출력된다. 이런 순서로 프로그램이 실행 될 수도 있다는 뜻으로 이해했는데 맞나요? 메모리 베리어를 사용하면 1) 위 경우처럼 순서가 뒤바뀌는 경우가 없어진다. -> 코드 재배치 억제 2) 두 스레드가 같이 사용하는 전역변수 _answer, _complete를 Store하고 Load하는 부분을 확실하게 할 수 있다.( = 물을 내린다...?) -> 가시성 이러한 이점이 있는거구요!
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Atomicity하게 만들기
interlocked 부분까지 수강하고 든 궁금증입니다. 추후에 나올 수 있으나 ㅠㅠ...... 우선 질문해보겠습니다. 원자성에 대하여 설명을 해 주실 때, 아이템 복사를 예시로 설명을 해 주셨는데요. 설명을 잘 해주셔서 쉽게 이해가 되긴하였는데 ㅠㅜ 이 아이템구매, 또는 거래에 대해서는 C# interlocked 함수로는 처리가 불가할것 같은데, (db갱신도 필요하고 소스 로직도 몇줄이나 처리될지 모르니) 이부분은 그럼 트랜잭션으로 원자성을 보존하나요? (mysql.data 에서 지원하는 트랜잭션 말씀드립니다.) 아니면 다른 방법이 있나요? + mysql을 주로 사용하는데 .data보다는 Entity 프레임웤을 추천하는 경우가 많은데, 서로 어떠한 장단점이 있나요? 저는 쿼리문에 더 익숙해 있는데 ㅜㅜ.. Entity 접근이 어렵더라구요. (물론 추후강좌에 있긴한데 (구매도하였음) 궁금해서요....)
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Release모드로 실행해도 정상적으로 작동하면 비정상인가요....?
저는 선생님이 보여주신 부분과 어셈블리 코드가 다릅니다ㅠㅠ 2E44412h가 _stop주소인거같고, 그 안에 들어있는 값과 0 이랑 비교하는거같은데, 음... visual studio 버전이 달라서 그런건가요...?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
TaskCreationOptions.LongRunning에 관해 질문 있습니다!
위에 다른분이 TaskCreationOptions.LongRunning에 관한 질문한 글을 봤습니다. 거기서 선생님이 하신 말씀으로는 "LongRunning 설정 시 그냥 새로운 쓰레드를 생성하게 됩니다." 라고 하셨고 아래 링크를 달아주셔서 확인해 봤습니다. https://stackoverflow.com/questions/10298641/is-it-true-that-for-long-running-processes-it-is-better-to-do-thread-manually-in 링크는 이거였고, 답글중에 ThreadPool thread is lightweight and cheap since could be rescheduled to serve a new request from the ThreadPool, so as soon as thread operation is done, ThreadPool could reschedule the same thread for other operation. 라는 답변이 있었는데요, 새로운 쓰레드를 생성하는게 아니라 스레드를 스케줄링한다(?) 라는 개념으로 해석되는데 어느것이 맞는건가요? 질문을 좀 요약하면 아래와 같을 것 같습니다.
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
싱글톤에 관하여
안녕하세요 싱글톤을 따라서 구현하다가 궁금한 점이 생겨 질문드리게되었습니다. ServerPacketManager 에서는 static PacketManager _instance; public static PacketManager Instance { get { if (_instance == null) _instance = new PacketManager(); return _instance; } } 이렇게 싱글톤을 만들었고 SessionManager 에서는 static SessionManager _session = new SessionManager(); public static SessionManager Instance { get { return _session; } } 이렇게 구현하셨는데 같은 싱글톤이죠? 굳이 다르게 구현하신 이유가 있나요?
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
sendbuffer에 관하여 질문있습니다
패킷을 만들면서 생각해보니 결국 마지막 count 값이 보낼 패킷의 전체 크기를 나타내는것 같은데 그렇다면 각 패킷마다 count를 먼저 계산하고 해당 count 크기의 바이트 배열을 만든다음 이 배열에 정보를 넣어서 보내는 방법이 더 메모리를 아낄 수 있지 않나요? 앞선 강의(SendBuffer)에선 가변적인 패킷의 길이를 알 수 없으므로 무작정 크게 잡는것이 메모리 낭비라고 하셨는데 count를 통해 패킷의 전체 크기를 알기 때문에 딱 맞춰서 보낼 수 있지 않나요?
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
패킷이 완전하지 않은 상태로 왔을 경우
안녕하세요 패킷 조립에 관하여 질문있습니다. [size(2)][packetId(2)][...][size(2)][packetId(2)][...]... TCP는 순서 보장이 되지만 한 번에 완전한 상태로 보냈는지는 보장이 안되는데 [size(2)] 를 Recv 한 후 [packetId(2)][...] Recv 하는 경우에 [size(2)] 가 처음에 왔을 경우 패킷이 완전체로 도착하지 않았기 때문에 break를 할 것이고 이후 [packetId(2)][...]가 오면 파싱 과정에서 패킷 아이디를 사이즈로 인식하여 잘못된 결과가 발생하지 않나요? 즉, 불완전한 패킷이 왔을 경우의 처리는 따로 하지 않나요?
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
chatPacket.chat 실행 결과에서 playerId가 섞여 나옵니다..!
안녕하세요!! 빠른 답변 항상 감사드립니다!! 실행결과 관련하여 질문드립니다! 실행결과 초반에는 playerId가 섞여서 출력되다가 이런식으로 playerid 별로 10번씩 출력되다가 마지막에는 또 이렇게 섞이는 식으로 출력됩니다... 코드가 잘못되어서 이런 결과가 나오는 걸까요..?
- 미해결[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
Buffer와 Packet에 관한 의문
안녕하세요 ㅎㅎ 강의를 들으며 세세한 것 보다 전체적인 흐름을 잘 이해하려고 노력중입니다. 몇 가지 흐름을 파악하다 의문이 생겨서 질문 드립니다. Q.1 PacketSession 클래스의 OnRecv함수입니다. while문의 첫번째 if문을 보면 일단 헤더의 size는 파싱할 수 있는지 체크를 하고 있는데요, 잠시 TCP의 성질을 보면 TCP통신의 경우 혼잡제어를 통해 서버가 혼잡하면 일부만 보내고 다시 원활해지면 나머지를 보낸다고 하셨습니다. 그렇다면 혼잡시에 패킷의 일부만 전송되어 SIZE만 보내진다거나 헤더를 제외한 데이터만 전송되는 경우도 있나요? 일부만 전송한다는 얘기가 패킷단위로 나눠서 보낸다는 말이지 패킷을 쪼개서 보내지는 않는다는 뜻인건가요? Q.2 100명의 유저가 같은 장소에서 모두 움직이면 10000개의 패킷이 전송될것이고, Send를 호출하는 부분이 데이터 복사와 같은 무거운 작업들이 많이 일어나니 컨텐츠단에서 SendBuffer라는 대용량 버퍼를 만들고 거기에 차곡차곡 넣어서 유저당 한번씩만 전송하도록 하여 총 100개의 패킷만 전송하도록 하는 것이 목적인가요? 제대로 이해했는지 아리송합니다 ㅠㅠ Q.3 SendBuffer 클래스가 있고 사용하기 편하게 인터페이스를 뚫어준 SendBufferHelper 클래스가 있는데 애초에 SendBuffer를 사용하는 쪽에서 편하게 인터페이스를 뚫어줄 수도있는데 별도 SendBufferHelper클래스를 사용하시는 이유가 있나요?!! 선생님처럼 Helper Class를 작성하면 단기적으로, 장기적으로 어떤 이점이 있는지 궁금합니다. 아직 이와같은 설계가 너무 낯설어서 많이 배우고 알고싶습니다! Q.4 SendBufferHelper에서 Open시 요구한 사이즈보다 버퍼 여유공간의 크기가 작으면 new 를 통해 새로운 버퍼를 할당하게 되는데요 이전에 사용하던 버퍼는 누군가 잘 사용하다가 더이상 참조가 없어지면 가비지 컬렉터에 의해서 메모리 정리가 잘 되는건가요? 너무 쿨하게 new로 새로운 메모리 공간을 할당해서 조금 의문이 생기네요. SendBuffer의 경우 전송후에 더이상 참조할 일이 없기에 가능한 Send만의 특징이겠죠?
- 해결됨[C#과 유니티로 만드는 MMORPG 게임 개발 시리즈] Part4: 게임 서버
서버 흐름에 관하여 질문있습니다
안녕하세요 서버 흐름을 정리하다가 궁금한점이 생겨 질문드리게 되었습니다. 제가 정리한 바로는 1. Server프로젝트의 Program에서 Listener를 Init(주체 : main thread) 2. Listener Init 내부에서 AcceptAsync를 호출하고 Program의 무한루프 실행(주체 : main thread) 3. AcceptAsync가 완료되면 OnAcceptCompleted실행(주체 : AcceptAsync로 부터 나온 쓰레드 = a쓰레드) 4. OnAcceptCompleted 내부에서 Session 생성 및 해당 Session의 Start함수 호출(주체 : a쓰레드) 5. Start함수 내부에서 RegisterRecv함수 호출(주체 : a쓰레드) 6. RegisterRecv 내부에서 ReceiveAsync 호출(주체 : a 쓰레드) 7. OnConnected 및 RegisterAccept호출(주체 : a쓰레드) 8. ReceiveAsync는 클라이언트로부터 요청기다림(주체 : ReceiveAsync로 부터 나온 쓰레드 = b쓰레드) 이후 과정은 생략... 반복... 질문1 ) 위와 같은 과정이라고 정리했는데 맞나요? 질문2 ) 맞다면 각 세션(소켓)마다 Receive를 위한 쓰레드가 배정되어 있나요?(7,8번 과정의 반복의 결과)(세션 수 = Receive 쓰레드 수) 질문3 ) 찾아보니 Async는 쓰레드 풀을 이용하는 것 같은데 세션마다 Receive를 하기 위해 생성된 쓰레드가 요청 대기 중이고 풀에 돌아오지 못한 상태에서 접속자 수가 많아지면 쓰레드 풀(인력)이 부족해져 서버가 멈출 수 있나요? 전체적인 흐름에 대해서 질문드리다 보니 앞에서 배웠던 내용들을 합치는 과정에서 궁금한 점이 생겨 계속 비슷한 개념 내용으로 질문을 드리네요... 죄송합니다... 읽어주셔서 감사합니다!
- 미해결[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쓰레드 이상) 읽어주셔서 감사합니다.