포스트

[RHTF] Protobuf 패킷 타입 구분하기

현재 문제점

문제의 코드에서는 패킷을 모두 protobuf가 아니라 구조체로 작성했을 때, 유효했습니다.

그러나 이 프로젝트에서는 Protobuf를 사용한 패킷 통신이기 때문에 문자열을 그대로 해석하면 정상적인 해석이 불가능합니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
void process_packet(int c_id, char* packet)
{
    switch (packet[1])
    {
    case User::NUM::C2SLoginUserReq:
    {
        // ...
    }
    break;
    case User::NUM::S2SLoginUserReq:
    {
        // ...
    }
    break;
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
syntax = "proto3";

package User;

enum NUM {
	C2SLoginUserReq     = 0;
	S2SLoginUserReq     = 1;
}

message C2SPCLoginUserReq {
    NUM Type            = 1;
	uint32 UserID       = 2;
}

message S2CPCLoginUserRes {
    NUM Type            = 1;
	uint32  UserID		= 2;
	string  UserName	= 3;
	uint32  UserLevel	= 4;
}


해결 방법

따라서 위의 문제점을 해결하고자 위의 .proto 파일을 다음과 같이 변경하였습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
syntax = "proto3";

package User;

enum NUM {
	C2SLoginUserReq = 0;
	S2SLoginUserReq = 1;
}

message Default {
	uint32 Size = 1;
	NUM Type	= 2;
}

message C2SPCLoginUserReq {
	uint32	Size	= 1;
	NUM		Type	= 2;
	uint32 UserID	= 3;
}

message S2CPCLoginUserRes {
	uint32	Size		= 1;
	NUM		Type		= 2;
	uint32  UserID		= 3;
	string  UserName	= 4;
	uint32  UserLevel	= 5;
}


모든 패킷이 크기와 타입 정보 갖도록 수정하였습니다. 또한 크기와 타입만 갖고 있는 Default message 를 통해서

현재 수신한 패킷의 타입을 확인할 수 있도록 C++ 코드를 아래와 같이 수정하였습니다.


1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
void process_packet(int c_id, char* packet)
{
    User::Default buffer;
    buffer.ParseFromString(packet);
    User::NUM packet_type = buffer.type();

    switch (packet_type)
    {
    case User::NUM::C2SLoginUserReq:
    {
        // ...
    }
    break;
    case User::NUM::S2SLoginUserReq:
    {
        // ...
    }
    break;
    default:
    {
        printf("Invalid packet! [%d]\n", packet_type);
    }
    break;
    }
}


개선할 점

protobuf의 모든 메시지에 size, type을 작성하는 것은 새로운 메시지를 생성할 때 마다

작성해줘야 하기 때문에 비효율적이라고 생각됩니다.

따라서 이 점을 개선하기 위해 좀 더 연구가 필요합니다.

이 기사는 저작권자의 CC BY 4.0 라이센스를 따릅니다.