java

java google protobuf ByteBuffer 사용

kimbs0301 2025. 3. 17. 22:43

google protobuf와 java.nio.ByteBuffer 클래스 사용

 

build.gradle

dependencies {
...
    implementation 'com.google.protobuf:protobuf-java:4.29.3'
...
}

 

MyProtocolS2C.proto

syntax = "proto3";

package MyProtocolS2C;

option java_multiple_files = true;
option java_package = "com.protobuf";
option java_outer_classname = "MyProto";

// protobuf는 하단에 추가만 해야한다.
message EchoMessage {
    int32 sequence = 1;
    int32 id = 2;
    int64 timestamp = 3;
    string message = 4;
}

 

protobuf는 새로운 필드 추가 시 하단에 추가만 해야 한다.
필드 삭제도 서버와 클라이언트 간 패킷 클래스 버전 동기화가 필요하다.

 

명령 프롬프트에서 자바 파일 생성

> C:\tools\protoc-29.1\bin\protoc.exe -I=./ --java_out=./src/main/java ./MyProtocolS2C.proto

 

PacketConst.java

public interface PacketConst { // Const
    int BUFFER_SIZE_DEFAULT = 1024 * 4;
    //
    int MSG_ID_SIZE = 1;
    int BODY_SIZE = 4;
    //
    int HEADER_SIZE = MSG_ID_SIZE + BODY_SIZE;

    interface Type { // Const
        byte PUSH = 0x07;
    }
}

 

SendPacket.java

import com.google.protobuf.CodedOutputStream;
import com.protobuf.EchoMessage;
import java.nio.ByteBuffer;
import java.util.Arrays;
...
EchoMessage sendMessage = EchoMessage.newBuilder()
	.setId(1).setSequence(1).setTimestamp(1).setMessage("a")
	.build();

int bodyLength = sendMessage.getSerializedSize();
...
ByteBuffer bb = bufferPool.acquire(1024);
// ByteBuffer bb = bufferPool.acquire(PacketConst.HEADER_SIZE + bodyLength);
bb.limit(PacketConst.HEADER_SIZE + bodyLength);
bb.put(PacketConst.Type.PUSH);
bb.putInt(bodyLength);

byte[] sendBytes = bb.array();
CodedOutputStream output = CodedOutputStream.newInstance(sendBytes, PacketConst.HEADER_SIZE, bodyLength);
sendMessage.writeTo(output); // try catch
bb.position(PacketConst.HEADER_SIZE + bodyLength);
bb.flip();
...

 

RecvPacket.java

import com.google.protobuf.CodedOutputStream;
import com.protobuf.EchoMessage;
import java.nio.ByteBuffer;
import java.util.Arrays;
...
ByteBuffer bb ...
...

byte[] recvBytes = new byte[PacketConst.HEADER_SIZE + bodyLength];
bb.get(recvBytes, 0, recvBytes.length);
System.out.println(Arrays.toString(recvBytes));

EchoMessage recvMessage = EchoMessage.newBuilder()
	.mergeFrom(recvBytes, PacketConst.HEADER_SIZE, bodyLength) // try catch
	// mergeFrom(bb.array(), PacketConst.HEADER_SIZE, bodyLength) // try catch
	.build();
System.out.println(recvMessage.getId());
System.out.println(recvMessage.getSequence());
System.out.println(recvMessage.getTimestamp());
System.out.println(recvMessage.getMessage());