Packet Generator #5

CJB_ny·2022년 3월 3일
0

Unity_Server

목록 보기
43/55
post-thumbnail

1. 개선점 찾기

1) switch문 개선

클라 세션에서

이런식으로 스위치로 패킷아이디를 구분을 해주고 있었는데

사버 <-> 클라 네트웍 통신이 많을텐데

운이 안좋게 PlayerInfoReq가 199번째 switch문이라면

쓸데없는 스위치 비교를 198번동안이나 하니까

이것을 개선을 하는게 첫번째

2) switch문 내부에서 파싱하는 부분 개선

ase PacketID.PlayerInfoReq일 경우

안에서

이런식으로 파싱을 해주고 있었는데

이러한 부분도 굉장히 귀찮은 작업이니 이부분도 자동화를 할 수 있도록 만들어주자.


그래서 2)번 부분을 쉽게 하기위해서

PlayerInfoReq와 같은 패킷은 IPacket이라는 것을 상속 받도록 만들어서

파싱을 할때 공통 인수로 넣어주면 편하다

그래서 이런 인터페이스를 파주고 이녀석은

이렇게 인터페이스를 구현하자

그래서 이제

IPacket을 상속받는 애들은 무조건 이 3가지를 구현을 해주어야 한다.

프로토콜을 사용하는 부분인 밑줄친 부분이 들어가면된다.

그리고 IPakcet > PacketFormat에 복붙 ㄱㄱ

이쯤에다가 넣어주도록 하자.

그리고

이런 구현부분도 PacketFormat에다가 넣어 줘야한다.

그리고 packetFormat에다가 {0}으로 해주도록 하자. ( 추가로 IPacket 상속 )

그리고 PacketGenerator 실행하고 배치파일 실행하면

이렇게 갱신되어있다.

프로토콜도 잘 갱신되어진다.


PacketHandler

그리고 Server에서 Packet폴더 안에

PacketHandler.cs, PacketManager.cs 추가 ㄱㄱ

PacketHandler의 경우 우리가 수동으로 관리를 할 것이다.

해당 패킷이 다 조립이 되었으면

무엇을 호출할지 맞춰 줄 것이다.

함수이름은 호출하는 "패킷이름 + Handler"

이렇게 해주는데

인자는 우리가 그냥 어떤것을 받으면 가장 좋을지 생각해서 넣어준 것이다.

Session은 어떤 세션에서 조립이 되었느냐 이고

그리고

IPacket packet은 어떤 패킷이냐? 이다.

그리고 클라세션에 있던 부분

이부분을 잘라와서 붙여 넣어야한다.

이까지 했으니까 이제

이부분을 이제 자동화 하는 부분을 만들어 줘야 하는데

이부분은 어디서 하느냐? 인데

이부분을 이제 PacketManager에서 할 것이다.

이녀석은 패킷핸들러를 다 등록을 시킨다음에는 뭔가를 수정할 것은 없기때문에

"싱글톤"으로 만들어 주도록 하자.

이렇게 인스턴스를 만들어 주도록 하자.

싱글톤이 단순하면서도 편리한데

이제 PacketManager를 사용하고 싶다면은

PacketManager.Instance를 사용하면은

여기 static에 들어가있는 변수를 바로 반환해가지고

PacketManager가 전체코드에서 하나만 있는 것처럼 사용이 가능하다.

그리고 이렇게 받아주도록 하자.

클라세션의 이부분을 옮기도록 하자.

이렇게

그리고 클라 세션에서는

이렇게 연결을 해주도록 하자.

(this 는 ClientSession이다 )


이제 PacketManager에서 switch문이 아니라 자동으로 등록을 해주는 부분을 만들도록 하자.

딕셔너리로 구분을 해줄 것인데

처음에는 프로토콜 아이디로 구분을 하고 두번째로 어떤 행동을 할 것인지를 정할 것이다.

그래야 해당 프로토콜 아이디를 보고 뭘 할지 정할 수 있기 때문에...

그래서 이런 딕셔너리를 만들 것이다.

그래서 이제 프로토콜 아이디랑 어떤 작업을 할지 넣어 줘야한다.

Register라는것을 만들어서 모든것을 등록을 하는 작업을 만들도록 하자.

PacketGenerator에서 했던것처럼 처리를 해주도록 하자.

이렇게 해당 패킷 번호를 넣어주고 이 녀석이 무슨 행동을 할지 넣어 줘야 한다.

그리고 MakePacket이라는 행동을 해주면되는데

이 녀석을 밑에 다시 만들면 된다.

MakePacket의 인자는 이렇게 받고 조건을 이따구로 해주자.

스위치 문의 이부분을 해주고 있었으니까

이렇게 해주는데 패킷이 다 PlayerInfoReq가 아닐테니

이렇게 바꿔줘야 할 것이다.

이렇게 T타입의 패킷을 만들어 준다음에는

이제 PacketHandler쪽으로 이 인터페이스를 넘겨 주어야 한다.

그래서 Handler에 전달을 해주기 위해서

딕셔너리를 하나 더 만들어서

이 형식에 맞게

Action타입을 설정 해주면된다.

그리고 이렇게 이름을 지어 주도록 하겠다.

이렇게 만들었으니 Register를 하는데

첫번째 경우에는 만들어 주는것을 등록하는 것이고

(ushort)PacketID.PlayerInfoReq는

PacketHandler.PlayerInfoReqHandler로 넘겨달라는 것이된다.

그리고

밑줄 친 부분의 이름은 우리가 규약을 하나 만들었었다.

그게 바로 아까 말한

"패킷 이름" + Handler인 것을 붙여 주면되고

그리고 그것을 PacketHandler에다가 준비를 해주면된다.


그래서 MakePacket을 이제 호출을 하면은

(코드를 짜놓은 것인데)

55~56 에서 실제로 패킷을 만들어 준다음에

58~60까지 실제로 Handler를 호출해주는 작업까지 한 것이다.

그래서 이제

이부분에서 스위치문을 쓰는게 아니라

_onRecv에다가 어떤패킷과 액션인지를 찾아서 호출을 해주면된다.

지금은 _onRecv에는 MakePacket이라는 애가 등록이 되어있으니까

OnRecvPacket에다가

이런식으로

id, action이 있다면 해당하는 id가 있는 것이니까

action.Invoke를 통해 알려주도록 한다.


2. 코드흐름

흐름을 다시 보면

먼저 클라 세션에서 패킷을

이렇게 넘겨 준것이다.

그럼 PacketManager의

이부분에서는 처음에

size, id를 긁어 와가지고

id에 따라가지고 switch 문으로 하던것을

이렇게 더 편리하게 딕셔너리로 찾아온 다음에

실제로 Handler를 등록을 해놨으면은

action.Invoke를 해줄 것이다.

그러면 MakePakcet이 호출이 될 것인데

그 이유는 우리가 등록을 할때

MakePacket을 등록을 해놓았었다.

이것을 PlayerInfoReq로 등록을 해놓아서

여기서 패킷은 PlayerInfoReq라는 패킷이 만들어 지면서

Read를 해서 DeSerialization을 한다음에

이녀석과 연관된 Handler를 호출 하면서

최종적으로는

PacketHandler에 등록한

이부분이 호출이 될 것이다.


Register하는 부분

그리고 이런거 하기 앞서서

Register하는 부분을 언젠가는 하기는 해주어야 한다.

그래서 멀티쓰레드가 개입하기 전이나 개입을 못하는 상황에서 Register를 등록을 해주도록 하자.

그냥 맨처음에 등록을 해 주도록 하자.

Server > Program에서

이렇게 하고

테스트를 위해 실행을 해보면

잘된다


그래서 이제부터는

그래서 PacketGenerator에서 PacketManager만 잘 생성? 해주면

PDL에 내용을 추가를 해도

굳이 PDL의 내용을 파싱하고

new하는 부분을 신경쓸게 아니라

여기있는

PacketHandler에다가

이녀석을 처리해주는 인터페이스 함수 하나만 파주면 된다는 말이다.

profile
https://cjbworld.tistory.com/ <- 이사중

0개의 댓글