개인공부) 서버실습(36) - Packet Generator(2)

Justin·2022년 7월 2일
0

서버공부

목록 보기
35/45
post-thumbnail

✅ 지난 시간

간단하게 패킷 자동화를 어떻게 할 수 있을지에 대한 개념이해를 위해 큰 틀을 짜놓는 작업을 하였다.

xml파일에 담긴 데이터를 읽어와 각 타입에 맞게 변화시키는 작업이 귀찮지만 굉장히 유용해서 추후 다른 프로젝트에서도 종종 사용할 수 있을 것 같다.

🌐 GenPackets.cs

🔹 생성

using (XmlReader x = XmlReader.Create("PDL.xml", settings))
            {
                x.MoveToContent();
                while (x.Read())
                {
                    if (x.Depth == 1 && x.NodeType == XmlNodeType.Element)
                        ParsePacket(x);
                }
                File.WriteAllText("GenPackets.cs", genPackets);
            }

기존에 using문을 통해 랩핑해준 영역에서 while문이 종료되는 시점에 File.WriteAllText(저장경로, 내용)를 통해 GenPackets.cs 파일을 만들어준다.

🔹 내용 넣기

ParsePacket()에서 ParseMembers() 호출 이후의 데이터를 genPackets에 지난 시간에 선언해준 PacketFormat.packetFormat형식으로 담아준다.

genPackets += string.Format(PacketFormat.packetFormat,
            packetName, , ,);

packetFormat은 총 4개의 값들({0}~{3}) 까지를 채워 넣어주어야 하기에 해당 값들은 아래에서 가져와 담아준다.

🔵 ParseMembers() - 기본

기존 void 타입이었던 함수를 Tuple<string, string, string> 로 선언하여 3개의 값을 리턴하도록 한다. *packetname의 경우는 이미 존재하기에

Tuple
메서드로부터 복수 개의 값들을 리턴받을 수 있는 기능

Switch문을 통해 memberType에 따라 동작 코드를 구분해 놓은 곳에 각 타입에 맞게 값을 담아준다.

PacketFormat - memberFormat에 필요한 두 가지일 경우 아래와 같이 미리 선언해둔 memberType, memberName을 넘겨 주고,

memberCode += 
string.Format(PacketFormat.memberFormat, 
memberType, memberName);

readCode, writeCode 모두 같은 형식으로 담아준다. 여기서 readCode에 memberType의 경우는 ToInt16같은 변환 타입이 필요한 위치이기에 함수를 만들어 값을 구해준다.

🔹 ToMemberTyep(string memberType)

간단하게 각 타입별로 지정된 변환타입으로 return 값을 날려주면 된다.

🔵 ParseMembers() - string

string도 물론 비슷하지만, 아래와 같이 제작 시에 사용한 형태가 다르기에 Format 타입을 변경하여 그에 맞는 값을 넣어준다.

🔵 ParseMembers() - List

list 형식은 앞서 Tuple 리턴값을 가진 ParseListPacket()을 만들고, 값을 받아와 Tuple.Item숫자 이렇게 뽑아서 사용하면 된다.

🔸 ParseListPacket()

리스트 형식 처리를 위한 함수를 제작한다. 우선 예외 처리를 위해 검사를 먼저 해주고,

public static Tuple<string, string, string> ParseListPacket(XmlReader x)
        {
            string listName = x["name"];
            if (string.IsNullOrEmpty(listName))
            {
                Console.WriteLine("List without name");
                return null;
            }

Tuple 타입으로 memberCode에 넣기위한 값을 가져와 담아주고 나머지 값들은 이름의 대소문자 이기에 이를 가져오기 위한 함수를 따로 제작한다.

🔸 FirstCharToUpper, Lower

크게 복잡한 거는 없고, 첫 문자 값만 대문자 or 소문자로 바꿔주는 기능을 한다.

public static string FirstCharToUpper(string input)
        {
            if (string.IsNullOrEmpty(input))
                return "";
            return input[0].ToString().ToUpper() + input.Substring(1); // substring은 인자 부터 값 시작
        }

        public static string FirstCharToLower(string input)
        {
            if (string.IsNullOrEmpty(input))
                return "";
            return input[0].ToString().ToLower() + input.Substring(1);
        }
    }

그 뒤에 저장해두었던 Format에 맞추어 값을 잘 넣어주면 된다.

🔸 ParseMembers() 최종

그렇게 적용한 함수 및 값들을 해당 Format에 맞게 담아주기만 하면 작업은 끝난다.

public static Tuple<string, string, string> ParseMembers(XmlReader x)
        {
        	... 지난 시간 작성한 내용
        
         switch (memberType)
                {
                    case "bool":
                    case "byte":
                    case "short":
                    case "ushort":
                    case "int":
                    case "long":
                    case "float":
                    case "double":
                        memberCode += string.Format(PacketFormat.memberFormat, memberType, memberName);
                        readCode += string.Format(PacketFormat.readFormat, memberName, ToMemberType(memberType), memberType);
                        writeCode += string.Format(PacketFormat.writeFormat, memberName, memberType);
                        break;
                    case "string":
                        memberCode += string.Format(PacketFormat.memberFormat, memberType, memberName);
                        readCode += string.Format(PacketFormat.readStringFormat, memberName);
                        writeCode += string.Format(PacketFormat.writeStringFormat, memberName);
                        break;
                    case "list":
                        Tuple<string, string, string> t = ParseListPacket(x);
                        memberCode += t.Item1;
                        readCode += t.Item2;
                        writeCode += t.Item3;
                        break;
                    default:
                        break;
                }
        }

📜 테스트 결과

이제 작동을 시켜보면 GenPackets라는 파일이 생성되고 내용이 담겨있는 것을 확인할 수 있다.

다만 아마 파일 내용의 배치가 뛰어쓰기가 안되어있어 어색할텐데 이렇게 Replace를 사용하여 공백인 경우 Enter 한 것과 같이 보이도록 작업을 해줄 수 있다

memberCode += memberCode.Replace("\n", "\n\t");
readCode += readCode.Replace("\n", "\n\t\t");
writeCode += writeCode.Replace("\n", "\n\t\t");

정리가 되면 새로 생성된 코드를 기존 ClientSession, ServerSession에 담아서 테스트 돌려보면 다시 정상적으로 동작하는 것을 확인할 수 있다.


PacketFormat 제작 시에 Count에 값 더하는 게 하나가 들어가지 않아서 계속 실행이 안되어 한참 원인을 찾았다.

Packet 영역을 구성할 때는 진짜 하나하나 신경을 잘 써야겠다.. 아니라면 바로 이렇게 동작하지 않아버리니 ㅠㅠ

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

0개의 댓글