Question

I'm trying to send int data via UDP using protobuf. from visual c++ to Java(Android Studio)

proto file:

message rbr
{
  required int32 rpm = 1;
  required int32 gear = 2;
  required int32 speed = 3;
}

C++ sending:

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) receive using square wire protobuff library:

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

The data is received correctly if the value is below 127, when I send 128 the result is 3104751. But it works fine when I try to receive it in Visual C++ too.

updated code to use SerilizeToArray

int size = telemetry.ByteSize();
char* array = new char[size];
telemetry.SerializeToArray(array, size);        
memset(message, '\0', BUFLEN);  
memcpy(message, array, size);

but how to receive on java? i try this code but not working.

packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);                    
byte[] bytes = packet.getData();
rbr newMsg = wire.parseFrom(bytes, rbr.class);
Was it helpful?

Solution

Using string as a byte array holder and calling String.getBytes() is a bad practice that always leads to the broken code.

You are using Message.SerializeToString on the C++ side, so you should use something like com.google.protobuf.TextFormat.merge(CharSequence,MessageBuilder) on the Java side to parse the protobuf text-format.

Better yet, instead of the text-format use the normal binary representation. The generated message and builder classes provide serialization and deserialization methods that work directly with byte arrays (and also streams in Java), and sending and receiving a byte array over the UDP is (arguably) more natural then converting something to string and then converting that string to byte array and back.

OTHER TIPS

i found it , oleg was right, the problem is because i convert it to string. now i directly copy the byte from packet.

byte[] bytes = Arrays.copyOfRange(packet.getData(),0,packet.getLength());
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top