1일차에 만든 game.pb.go를 토대로 핑 보내보기
package main
import (
"fmt"
"game-server/protocol"
"time"
"server/protocol"
"google.golang.org/protobuf/proto"
)
func main() {
// 1. ping 패킷 만들기
ping := &protocol.CS_Ping{
Time: time.Now().UnixMilli(),
}
fmt.Println("만들어진 핑 : ", ping)
// 2. 패킷을 직렬화 (struct -> []byte)
data, err := proto.Marshal(ping)
if err != nil {
panic(err)
}
fmt.Println("직렬화된 핑 : ", data)
// 3. 직렬화 된 패킷을 역직렬화 ([]byte -> struct)
var decoded protocol.CS_Ping
err = proto.Unmarshal(data, &decoded)
if err != nil {
panic(err)
}
fmt.Println("역직렬화 된 핑 : ", decoded)
}-
참고 : Go에서 := 연산자는 “지역” 내에서만 가능함!
-
참고 2 : var 변수명 형식명 ← 으로 변수 선언 가능함.
-
Go 파일 실행하는 방법
// main.go 있는 데에서 실행하면 됨
go run ./server에러가 뜨면서 안됨

- no required module provides package 어쩌구
- 패키지가 없다는 의미
- go.mod 있는 곳으로 가서 아래 명령어 실행
go mod tidy
- not in std 어쩌구
- protocol 모듈을 못 찾았다는 의미
protobuf로 정의한 패킷 만들어서 뜯어보기 성공!

패킷을 추상화 하기
- 모든 메시지를 하나의 형태로 일단 정의를 해서, 패킷의 타입에 따라 분기할 수 있도록 만듬
- 이전에 컴공 캡스톤디자인 할 때 만들었던 통신 프로토콜이 이렇게 생겼었음

- 여기서 말하는 커맨드가 패킷 타입. 아래의 사진처럼 만들려고 하는 것

/* ===================
메시지 타입
=================== */
enum MessageType {
MESSAGE_TYPE_UNSPECIFIED = 0;
PING = 1;
PONG = 2;
// 추후 확장 가능
}
/* ===================
공통 패킷
=================== */
message Packet {
MessageType type = 1;
bytes payload = 2;
}
/* ===================
실제 메시지들
=================== */
message Ping {
int64 timestamp = 1;
}
message Pong {
int64 timestamp = 1;
}// 추상화 한 패킷을 뜯어보기
func main() {
// 1. Ping 메시지 만들기
ping := &protocol.Ping{
Timestamp: time.Now().UnixMilli(),
}
// 2. Ping 을 []byte로 만들기
payload, err := proto.Marshal(ping)
if err != nil {
panic(err)
}
// 3. []byte 로 만든 Ping을 공통 패킷으로 감싸기
packet := &protocol.Packet{
Type: protocol.MessageType_PING,
Payload: payload,
}
// 4. 감싼 공통 패킷을 직렬화 (실제 네트워크로 보내지는건 이게 보내짐)
data, err := proto.Marshal(packet)
if err != nil {
panic(err)
}
// ==== 서버가 해당 핑 메시지를 받았다고 치고 처리해보기 ====
var recvPacket protocol.Packet
err = proto.Unmarshal(data, &recvPacket)
if err != nil {
panic(err)
}
switch recvPacket.Type {
case protocol.MessageType_PING:
var recvPing protocol.Ping
_ = proto.Unmarshal(recvPacket.Payload, &recvPing)
fmt.Println("받은 핑 : ", recvPing.Timestamp)
default:
fmt.Println("모르는 메시지 타입이 들어옴.")
}
}
-
비유를 하자면, 배달을 시켰다고 가정하자.
-
실제로 배달이 온 음식이 payload, 배달 영수증이 MessageType, 이걸 다 감싸서 온 Packet이 전체 배달 봉지 쯤 될 듯.
-
음식점 (서버) 에서 배달 보내기 위해 음식 (payload)을 준비하고, 영수증 (MessageType)을 앞에 붙인 다음에 이걸 비닐봉지(Packet)로 감싸서(Marshal, 직렬화) 보냄.
-
그럼 주문자 (클라이언트)는 이걸 받아서 포장의 역순으로 까서(Unmarshal, 역직렬화) 확인하면 됨.
-
이정도면 된다고 생각했는데, 다음 단계로 알아야 할 게 있었다.

- 그렇다. 분할로 음식을 보낼 수도 있던 것이었다!
다음에 할 것
- 길이 프레이밍에 대해 알아보기