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());

'java' 카테고리의 다른 글

java bucket index  (0) 2025.03.17
java jsckson2 라이브러리 사용 null and default value ignore  (2) 2024.10.08
spring boot 가상 스레드로 웹소켓 사용  (0) 2024.07.20
java time ticks  (0) 2024.07.05
java drawing random  (1) 2024.07.05