我正在尝试使用protobuf通过UDP发送int数据。从visual c ++到Java(Android Studio)
原型文件:
message rbr
{
required int32 rpm = 1;
required int32 gear = 2;
required int32 speed = 3;
}
C ++发送:
telemetry.set_rpm(1200);
telemetry.set_speed(120);
telemetry.set_gear(4);
telemetry.SerializeToString(&serializedMessage);
memset(message, '\0', BUFLEN);
memcpy(message, serializedMessage.c_str(), serializedMessage.size());
//send the message
if (sendto(s, message, serializedMessage.size(), 0, (struct sockaddr *) &si_other, slen) == SOCKET_ERROR)
{
printf("sendto() failed with error code : %d", WSAGetLastError());
exit(EXIT_FAILURE);
}
Java(Android)使用方线protobuff库接收:
socket = new DatagramSocket(8888);
Wire wire = new Wire();
while (true) {
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
s = new String(packet.getData(), 0, packet.getLength());
byte[] bytes = s.getBytes();
rbr newMsg = wire.parseFrom(bytes, rbr.class);
sGear = newMsg.gear.toString();
sRpm = String.valueOf(newMsg.rpm);
sSpeed = newMsg.speed.toString();
tvRpm.post(new Runnable() {
public void run() {
tvRpm.setText(sRpm);
tvGear.setText(sGear);
tvSpeed.setText(sSpeed);
}
});
}
如果值低于127,则正确接收数据,当我发送128时,结果为3104751.但是当我尝试在Visual C ++中接收它时,它工作正常。
更新代码以使用SerilizeToArray
int size = telemetry.ByteSize();
char* array = new char[size];
telemetry.SerializeToArray(array, size);
memset(message, '\0', BUFLEN);
memcpy(message, array, size);
但是如何在java上接收?我尝试这个代码,但没有工作。
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
byte[] bytes = packet.getData();
rbr newMsg = wire.parseFrom(bytes, rbr.class);
答案 0 :(得分:0)
使用字符串作为字节数组持有者并调用String.getBytes()
是一种不好的做法,总是会导致代码损坏。
您在C ++端使用Message.SerializeToString
,因此您应该在Java端使用类似com.google.protobuf.TextFormat.merge(CharSequence,MessageBuilder)
的内容来解析protobuf文本格式。
更好的是,而不是文本格式使用正常的二进制表示。生成的消息和构建器类提供直接与字节数组(以及Java中的流)一起工作的序列化和反序列化方法,并且通过UDP发送和接收字节数组(可以说)更自然,然后将某些内容转换为字符串然后转换为字符串到字节数组并返回。
答案 1 :(得分:0)
我发现它,oleg是对的,问题是因为我将它转换为字符串。现在我直接从包中复制字节。
byte[] bytes = Arrays.copyOfRange(packet.getData(),0,packet.getLength());