Packet Generator #1

CJB_ny·2022년 2월 25일
0

Unity_Server

목록 보기
39/55
post-thumbnail

1. 준비

그래서 int, string, List< struct > 등과 같은거

직렬화 해서 보내고

받을때는 역직렬화를 통해서 Raed하는 부분까지 해보았는데

이것을 이제 "자동화"를 하는 부분을 구현읋 하도록 하자.

자동화 코드를 만들때 방법이

먼저 "하드코딩" > 재사용하는 부분 찾기 > 자동화로 만들기

이렇게 하면될 것이다.


조금 자동화를 간략히 하기 위해

이부분 삭제 ㄱㄱ

->

그다음 packetId넣어주는 부분을 "생성자"에서 할게 아니라 (삭제)

여기서 밀어 넣어줘도 별다른 차이 x (override 없앰, Read도 똑같이)

여기서 이제 자동화를 만드는 부분을 시작하도록 하자.

그래서

자동화 만들기 위해서

솔루션 > 추가 > 새 프로젝트

콘솔 앱으로 만들고

다시 이뻐보이지 않으니까

솔루션 > 추가 > 새 솔루션 폴더 Tools 안에 넣자.

나중에 추가되는 Tools(조금 덜중요한것들 여기 밀어 넣을 것이다)

이렇게 일단 준비 끝


2. XML파일 만들기

그래서 클라 세션(최산화 되어있으니)

여기 있는 형식을 자동화를 해야되는데

그렇다는 것은 어딘가에는 "원본"에 대한 "정의"가 필요한데

그렇다는 것은

"패킷"의 "정의"를 어떤 방식으로 할지 다시 정해야 된다.

Json || XML 둘중 하나로 하면 됨.

(기타 => 자체적으로 정의한 IDL 사용도 됨)

XML을 조금더 선호를 하는데

그 이유는 JSON에 비해 하이럴키 (위계)가 잘보인다는 "장점"이 있어서


그럼 PacketGenerator > 추가 > 새항목 > 데이터 > XML파일

이렇게 가서 PDL(Packet Definition List)로 만든다.

이래 만들어짐

XML은 Header에 이런식으로 항상 정보가

이렇게 먼저 들어간다.

그 다음에 밑에다가 우리가 패킷에 대한정보를 만들어 줘야한다.

XML형식은 제대로 알 필요는 없고 쓰다보면

자연스럽게 알게된다.

이부분이랑 맞춰 줄려고 long, string이렇게 한거임

나중에 파싱을 하기위해서.

여기서가 이제 중요한데

List를 만들것인데

이렇게 < list로 > 감싸서 안에 id, level, duration을 넣게 되면

결국 이렇게 정의를 한게

우리가 클래스로 만들어준

이녀석을 정의를 한 것이다.

XML의 데이터만 긁어가지고 더미 클라의 서버세션의 구조를 알 수 있는 것이다.

그래서 이녀석을 파싱한다음에

똑같이 ServerSession에 있는 것을 자동생성을 해주는 툴을 만들면 되겠다.

그러면 XML은 이까지하고 XML을 파싱하는 부분을 만들어 줘야한다.


3. XML 파싱하기

그런데 이게 C++이라고 하면은

공식 라이브러리에서 파싱하는 그런게 없기 때문에

"오픈소스"중에서 하나를 골라서 사용을 해야되는데

C#은 다 어딘가에 마련이 되어있다.

using추가를 하고 일케

settings라는 애가 있는데 여기다가 옵션을 넣어 줄 수 있다.

여기다가 이제

이렇게 주석, 스페이스바 무시 옵션 ㄱㄱ

그리고 다 사용하고나면

Dispose로 닫아줘야하는데

이렇게말고

using 하면 다 끝나고 나서 알아서 Dispose를 호출해준다.

이렇게해서 진짜 한줄씩 읽는 지 확인을 해보도록 하자.


지금은 실행할때 Dummy, Server를 키고있었으니

PacketGenerator > 시작 프로젝트로 설정 ㄱㄱ

그리고 실행하면 > Error 뜸

이유는 오른쪽 Program class의 경로가 좀 달라서 그럼

PacketGenerator > 파일탐색기에서 폴더 열기

이런식으로 되어있는데

그런데

실제 이녀석이 읽어들이는 경로는 "실행파일"이 있는 경로로 읽어 들이기 때문에

한마디로 bin > Debug > net6.0 >

여기 exe 파일이 있는 경로를 기준으로 읽어들인다.

그래서 나중에 따로 설정을 할것이지만

여따가 PDL을 복사 ㄱㄱ

그러면 이제

이렇게 packet첫번째 줄부터 읽어들이는 것을 볼 수 있다.

그러면

r.Name으로 뽑아온게

지금 packet, long, string이런것이고 r[name]으로 뽑아서 온게

이런 부분이다.

playerId, name, skill . . .

여기 밑줄친 Attribute를 뽑아 온 것이다.

그리고 사실은 자동화 툴을 만들때 필요한것은 이게 "전부"다!

그래서 콘솔창 다시보면

마지막 두줄도 파싱을 한것을 볼 수 있다.


3. XML 패킷 실행

그래서 이게 패킷인지 아닌지를 구분을 해서 실행을 해줘야하는데

r.Name을 사용하는 것보다 다른 세련된 방법이 있다.

이렇게 해주면되는데

r.NodeType을 보면 아까

여기 닿는 (마지막 부분) packet, PDL도 떳었는데

XmlNodeType.Element가 제일 위에 packet PlayerInfoReq 에서 packet을 뜻한다.

끝나는 위치는 EndElement가 있다.


그런데 지금 왜 packet의 깊이 Depth가 1인지 모르겠다.

지금 이해 갔는데

이부분이 1이라 이부분 말하는 거같다.


그리고 패킷을 자동화를 해주기 전에 이것이 패킷인지 확인 작업을 할 것인데

Depth가 1일 때 ParsePacket에 들어와서

이렇게 체크를 해주도록 하겠다.

그리고 이름을 긁어오는데

이부분이

이부분이 될 것이다.

이렇게 ㅇㅇ.

그다음

안에 있는 녀석을 사용하기 위해 이 함수 파주어서 넘겨주도록 하자

그래서

이제

이 패킷안에 들어있는 부분을 파싱을 하기 위해

이따위로 해준다.

저 밑줄친 부분만 실행을 해야되니까

r.Depth + 1을 해주어야 한다.

r.Depth가 패킷의 깊이이니까 +1 해줘야함

r.Depth + 1를 해준게 우리가 파싱하려는 정보가 될 것이다


왜??


그래서 일단 while문 안은 이렇게 되는데

결국

이안에서 파싱을 하다가

이부분 만나면 다다르면 나가는 작업을 해주면 될 것이다.

그러면 이제 while안에서는 PDL을 파싱을 하는 부분인데

한번더 체크를 해주고

r.Name으로 타입을 구분을 해주도록 하자 (어떤 타입을 지원을 해줄 것인지)

자주 사용하는 것들을 지원해주도록 하자.

그래서 이 case에 따라서 자동화를 어떻게 다르게 해줄지 고민을 하면 되겠다.


4. PacektFormat 작성

" case에 따라서 자동화를 어떻게 다르게 해줄지 고민"을 하는 부분이 굉장히 막막한데

이렇때 굉장히 유용한 방법이 있는데

먼저,

1) 패킷의 format (형식)을 먼저 정의를 해준다.

2) 정의해준 패킷 format 가라치기 해주기.

이렇게 되는데

코드로 보여주도록 하겠다.


이안에 PacketFormat파일을 하나 만들어 주도록 하자.

그다음

ServerSession > 가서 무엇을 자동화를 해줄지 보도록 하겠다.

format을 하나 만들어 주는데,

여러줄에 걸쳐서 문자열을 정의하고싶을 때 @""를 사용하자.

그래서

요 안에다가 길어질 내용들을 넣는 것이다.

그다음 SeverSession의 PlayerInfoReq 싹다 복붙을 하고

이다음

고정적으로 들어가는 부부느 다르게 들어가야할 부분으로 가라치기 해야된다.

이런 부분은 XML파일에서 넣어주는 부분이니까

0번으로 바꿔치기 해주면된다.

( 그리고 일반적인 '{' == 소괄호는 '{{' 를 더 붙여줘야지만 '{'로 사용됬다는 것을 인식 할 수 있기때문에 더 붙여 주도록 하자.)

그리고 패킷이름은 달라질테니 맨처음 바뀔게 패킷이름이고

그다음 아까 {0}으로 해주었던부분 {1} 로 변경하도록 하자.

햇갈릴 수 있으니 주석을 남기며 진행을 하자.

지금 Read랑 Write가 남게되는데

모든 애들이 공통적으로 갖는 인터페이스 이다.

지금 밑줄 친 위에부분은 고적(공통적으로)들어가고

밑줄 부분부터 실질적인 데이터가 들어가는 부분이다.

그래서 {2}라 하고 진행을 하자.

이렇게 해주면 됨.

Write도 이까지는 똑같고

밑부분 부터 조금씩 달라질 것이다.

여기는 말그대로 패킷 id가 들어 가야하니까

패킷 아이디는 {0} 이니까 {0}으로 수정 ㄱ

그래서 여기부터가 달라지는 것인데

이부분 없앰

이부분은 마지막 최종 사이즈를 넣는 부분이다.

그래서 중간에 {3}번으로 넣어주자.

이런식

그리고 하나 더 파주는데

이녀석 같은 경우에는

이런 부분이 memberFormat으로 들어가게 되는 것이다.

이렇게 (더이상 추가할게 없어보인다)

그다음 넣어줘야 할 부분이 SkillInfo의

Read, Write부분의 자동화를 넣어 줘야한다.

그래서 이부분을 넣어주고 바꿔치기를 해줘야 한다.

여기서 뭘 바꿔치기를 해줄지 유심히 살펴보면은

이렇게 되고 밑줄 부분은 공용으로 다 들어가는 부분이다.

그리고 바껴야 하는게 BitConverter.{1} && sizeof({2}) 이렇게.

이렇게 가라치기!

그래서 일반적인 경우의 Read는 이렇기는 한데 string의 경우 양식이 조금 달랐다.

이런 식이였는데

뭐가 될지는 모르지만

이렇게 복붙 해주자.

그리고 밑줄 부분은 지금 ushort타입으로 밀어 넣고 있었기 때문에

ToUInt16는 '고정'이다.

사이즈를 2바이트 (ushort로)밀어 넣고 있었기 때문에

이렇게 가라.


이제 Write로 넘어 가면 될 것이다.

Write의

이부분을 "대표"라고 생각하고 복붙ㄱ

여기서 이제 다시 가라침

이렇게 수정.

그리고 string같은 경우는

이렇게 하고 있었으니까

이렇게 복붙하고 가라칠 부분들 수정ㄱㄱ

이렇게하고 끝


이렇게 해서 리스트를 제외한 형태

1) 일반적인 형태

2) string 형태

의 format 자동화의 templete을 만들어 준 것이다.

그래서 이녀석을 이용해서 뭔가 작업을 해주면 된다.

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

0개의 댓글