개인공부) 서버실습(41) - Chat(1)

Justin·2022년 7월 12일
0

서버공부

목록 보기
40/45

✅ 지난 시간

드디어 Packet Genrator 작업이 모두 끝났다. 코드 그 자체를 string 변수에 담아 패킷별로 생성해주는 방식으로 자동화를 한게 참 신선한 경험이었다.

내가 직접 했다면 그렇게 못했을 거 같은데, 이래서 다른 사람들의 코드를 분석하고 방법을 많이 찾아볼 필요가있다는 걸 알게도었다.

💨 추가 개선

예전에 작성해두었던 ServerCore-Session 클래스 안에 RegisterSend(), OnSendCompleted() 를 보면 중간에 접속이 끊겼을 때에 대한 처리가 없어 추가해주고자 한다.

🔧 RegisterSend()

RegisterSend에 들어왔을 때 Disconnect() 실행시 1로 변경해주는 _disconnected 변수 값이 1이라면 멀티 쓰레드로 인해 오류가 발생한 것이므로 return을 바로 시켜주고

소켓을 사용하는 _socket.SendAsync(_sendArgs) 부분 역시 안전하게 사용처리를 하기 위해 try, catch 구문으로 묶어 둔다.

RegisterRecv() 부분도 해당 함수처리와 동일하게 처리 해준다.

💬 Chat 예시

여기까지 작업을 하면서 네트워크 상에서 통신이 된다는건 알겠는데 이걸 어떻게 활용할 수 있는지 이해가 잘 되지 않았다.

강사님도 책을보면서 이 과정만 5번을 반복했지만 뭘 할 수 있는지 생각하기 어려웠다고 한다.

그래서 채팅을 만들어보면 패킷을 보내고, 다른 유저들에게 패킷을 뿌려주는 과정이 실제 MMO가 돌아가는 과정과 유사하여 더 이해하기 쉽게 될 것 같다.

🔷 PDL 내용 수정


클라에서 보낼 메시지 내용과 서버에서 어떤 사람이 보낸건지 확인하기 위한 id, 다시 뿌려줄 chat 내용 담을 변수 값들을 저장한다.

🔷 GameRoom Class 생성


유저들이 각 어떤 방(or 채널) 접속하고 나가는지 등을 관리하기 위한 GameRoom Class를 생성하고

Client session타입의 List를 만들어 들어왔을 때 추가, 나갈 때 제거 하는 코드를 작성

리스트가 아닌 딕셔너리로 관리해도 상관은 없다.

GameRoom 안전처리


여기도 멀티쓰레드 환경에서 난리가 날 수 있기에 한 번에 하나씩만 처리 되도록 lock을 걸어준다.

🔷 ClientSession

ClientSession에서 어떤 room을 가지고 있는지 알려주기 위한 선언

class ClientSession : PacketSession
    {
        public int SessionId { get; set; } 
        public GameRoom Room { get; set; }
        
        ...
        
    }

Server - Program

Main 코드 동작 시에 GameRoom을 인스턴스 해주고, static으로 선언하여 접근성을 높여준다.

public static GameRoom Room = new GameRoom();

🔷 Session Manager 생성


이제 기존 처럼 ClientSession을 새로 생성해서 넘겨주는 것이 아니라 Manager를 통해 생성해주고

어떤 클라이언트인지 몇개가 있는지 등을 관리하기 용이한 구조로 변경할 것이다.


간단한 싱글톤으로 SessionManager를 불러오면 session이 생성되도록 구현해준다. 생성, 찾기, 제거의 기능을 하는 함수를 제작해준다.

Session 생성

Session 찾기, 제거

변경하기

SessionManager Class에 만들어준 Generate함수를 통해 서버에서 listner가 동작할 때 새로 생성해주는 방식이되면서 어떤 세션들이 생기는지 관리를 할 수 있게된다.


유저들이 증가할수록 패킷에 따른 session들이 많이 필요한테니, 이렇게 관리해줄 필요가있다.

제거 위치

해당 연결이 끊어지는 경우 Remove를 해주며 해당 Session을 지워주면 된다.

🔷 ClientSession

ClientSession으로 다시 돌아와서 새로 생성한 Room에 현재 ClientSession을 연결해주며 방을 생성하고

연결이 끊어지는 시점에 방을 나가도록 위에서 제작한 함수 동작 위치를 지정해준다.

룸 입장 및 나가기

🌐 BroadCast

GameRoom 클래스로 다시 돌아와 같은 방에 있는 유저들에게 받은 메시지 패킷을 뿌려주는 함수를 제작한다.


위에서 PDL을 수정해주면 아래와 같은 변수타입이 생겼을 텐데, 새로 인스턴스를 해주고 현재 Session의 id 값과 채팅의 내용을 담아서 Write() 해주고

위에서 만들어준 list타입의 _sessions을 돌면서 패킷을을 전송해준다.

BroadCast 작동 위치

지난 시간에 언급했던 대로 PacketHandler는 각 패킷에 따라 다르게 처리할 수 있도록 작성해주어야 한다 했는데

이번에도 Chat형식으로 패킷을 변경하며 어떻게 처리할 건지 작성해주어야 한다.

파라미터를 통해 받아온 값들을 원하는 타입으로 캐스트한 뒤에 Room이 비어있지 않을 경우 BroadCast()를 동작 시켜 패킷을 뿌려주도록 한다.

정리

이번 시간에는 여기저기 돌아다니며 코딩을해서 내용이 헷갈릴거 같아 가볍게 정리를 하고자한다. 새롭게 추가 된 클래스는 아래와 같고 목적과 기능을 소개한다.

GameRoom
: 방을 만들고, 방에 입장한 유저(Session)들을 list에 담아두어 관리를 한다.
기능

  • 입장
  • 나가기
  • 전송하기(해당 방의 유저들에게 패킷을 전송해준다.)

SessionManager
: 처음 서버와 연결될 때 세션을 생성해주고, 관리하기 위한 SessionManager
기능

  • 생성
  • 찾기
  • 제거

전반적으로 설명하자면, 유저가 처음 입장을 요청하면 SessionManager를 통해 Session이 새로 생성되며 유저가 연결이 되고

연결이 됐을 때 Room에 입장이 되며, GameRoom 클래스는 해당 유저들을 저장해두고 서로 string 패킷을 주고 받을 수 있도록 환경 구현을 한 것이다.

profile
인디 게임을 만들며 공부하고 있습니다.

0개의 댓글