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 |