How send data from Python to Java using Protobuf? - java

Java Client
byte[] aReceiveData = new byte[1024];
DatagramPacket aReceivePacket = new DatagramPacket(aReceiveData, aReceiveData.length);
aServerSocket.receive(aReceivePacket);
ByteArrayInputStream aInput = new ByteArrayInputStream(aReceiveData);
Message test = Message.parseDelimitedFrom(aInput);
error
"Protocol message contained an invalid tag (zero)."
Python Server
mensagem = estoque_pb2.Message()
mensagem.type=1
mensagem.id=requestId
mensagem.methodId="test"
mensagem.obfReference="objectRef"
mensagem.arguments=resultado
return mensagem.SerializeToString()
self.udp.sendto(mensagem,self.client)
I am not able to send data from python to java using protobuf, thanks any help!

The received packet can be smaller than 1024 bytes, so one have to create ByteArrayInputStream only on received range of bytes.
The method parseDelimitedFrom intended to parse delimited messages. In fact it reads message length, and then reads message itself. As far, as I understood, your buffer contains only the message. Therefore, you have to use parseFrom method.
byte[] data = new byte[1024];
DatagramPacket pkt = new DatagramPacket(data, data.length);
socket.receive(pkt);
ByteArrayInputStream input = new ByteArrayInputStream(pkt.getData(), pkt.getOffset(), pkt.getLength());
Message test = Message.parseFrom(input);

Related

How to receive only actual data from a socket

i am sending 20 bytes of data from my udpserver to a client in java. At the client side i am receiving like this
byte[] buf = new byte[25];
final DatagramPacket recv = new DatagramPacket(buf,25);
String data = new String(recv.getData());
when i print data it is printing additional things. How can i only get my actual data. Please suggest.
You are sending 20 bytes, but you are allocating a receive buffer that can receive up to 25 bytes. The received datagram can be smaller, but you need to take the actual received length into account when constructing the String, eg:
String data = new String(recv.getData(), 0, recv.getLength());

Query an OpenTTD server

I am using the following java code to try to send a PACKET_UDP_CLIENT_FIND_SERVER (source) packet to query an OpenTTD server:
InetAddress address = InetAddress.getByName("publicserver-new.openttdcoop.org");
DatagramSocket socket = new DatagramSocket();
byte[] buf = new byte[]{0}; // 0 is number for CLIENT_FIND_SERVER, no extra data is needed (?)
DatagramPacket packet = new DatagramPacket(buf, buf.length, address, 3983);
socket.send(packet);
packet = new DatagramPacket(buf, buf.length);
socket.receive(packet);
packet.getData(); //
socket.close();
However, when I run the program the server never returns any packets. I have very little experience working with packets, and have been trying to figure out what to do by looking at PHP and Python source code that does the same thing. Hopefully someone will be able to help.
Thanks
EDIT:
I realized that the packet should actually contain the data 03 00 00, the first two bytes contain the length, but I still haven't been able to get a response using a Packet Sender. Maybe I am listening on the wrong port?
I figured out what I had been doing wrong. This line:
byte[] buf = new byte[]{0};
should be:
byte[] buf = new byte[]{0x03, 0x00, 0x00} (hex for clarity)
The problem was that the first two bytes store the length of the data
The third byte is the actual request
In addition, the DatagamPacket needs to be reset to allow more than 3 bytes to be read

UDP Packet sent not being read by server correctly

I'm sending two packets from a client to server. The issue I'm having is the data being read on the server makes both strings the same length with regards to the longest string sent. For example:
if string 1 was : 1234
and string 2 was: abcdefghi
the server would read
1234efghi
abcdefghi
It should just display
1234
abcdefghi
My code is:
byte[] toSendUser = new byte[1024];
byte[] toSendPass = new byte[1024];
String name = "1234";
String password = "abcdefghi";
toSendUser = name.getBytes();
toSendPass = password.getBytes();
DatagramPacket packSend = new DatagramPacket (toSendUser, toSendUser.length, ipConn, 9876);
connection.send(packSend);
DatagramPacket packSendtwo = new DatagramPacket (toSendPass, toSendPass.length, ipConn, 9876);
connection.send(packSendtwo);
Could it be a server issue or is my code wrong in my client?
DatagramPackets in Java keep shrinking to the size of the smallest one received so far. You have to either create a new one per receive(), or at least reset the length every time before the next receive().

java client python server sending udp data

I am trying to create a client in java which sends data to a python server using UDP,but i am having trouble sending data. Every example which i have seen or read so far is something like this:
byte[] buf = new byte[256];
InetAddress address = InetAddress.getLocalHost();
DatagramPacket packet = new DatagramPacket(buf, buf.length, ip,port);
System.out.println("Sending...");
socket.send(packet);
What i can't figure out is how can i send my data which can be of type int or char or string or even an array?? I mean how do I change these to byte,put it in buf and send them.
Can it then be simply be decoded on python client like this:
data,addr = self.sock.recvfrom(1024)
data = data.decode()
EDIT:
I have figured out how to convert strings to byte, by doing:
buf = "hello".getBytes();
But still no clue on integers and arrays..
You can create "protocole" JSON-based like this:
{"items":[ {"type":'string", "value":"test"}, {"type":"int", "value":3}]}
and use https://code.google.com/p/json-simple/wiki/EncodingExamples#Example_1-1_-_Encode_a_JSON_object to encode it.

How to convert class to byte array, as per the byte order of C and C++?

I am creating a class object to byte array see here, and passing this array to DatagramPacket to send at destination by means of UDP communication. At the destination side there is C application running and I am getting wired character. I damn sure this related to byte order. Because I am able to convert struct of C into class while receiving packet, but not able to do vice versa. Following is the sudo - code:
// recieving part
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet)
UdpPacket udp = new UdpPacket(buffer);
class UdpPacket implements Serializable
{
int a;
byte []message = new byte[10];
public UdpPacket(byte[] data)
{
ByteBuffer bb = ByteBuffer.wrap(data);
bb.order(ByteOrder.nativeOrder());
a = bb.getInt();
bb.get(message);
}
}
// sending ..
Converting UdpPacket object to byte array as per above mentioned link, but at the destination there is always junk values
DatagramSocket clientSocket = new DatagramSocket();
byte [] respoBytes = ObjectSerializer.serializeObject(udpPacket);
ByteBuffer bb = ByteBuffer.wrap(respoBytes);
byte []test = new byte[1116];
bb.order(ByteOrder.nativeOrder()); // tried all the orders here
bb.get(test);
DatagramPacket sendPacket = new DatagramPacket(test,test.length,client, Integer.parseInt(TxtFdPort.getText().toString()));
clientSocket.send(sendPacket)
;
The most obvious problem is that ignore the length of data read.
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
ByteBuffer bb = ByteBuffer.wrap(packet.getData(), 0, packet.getLength());
// you need to know the endianess, not hope it's the same.
bb.order(ByteOrder.LITTLE_ENDIAN);
int a = bb.getInt(); // asuming there is at least 4 bytes.
byte[] message = new byte[bb.remaining()];
bb.get(message);
For Sending I would just do this.
int port = Integer.parseInt(TxtFdPort.getText().toString());
byte [] respoBytes = ObjectSerializer.serializeObject(udpPacket);
DatagramPacket sendPacket = new DatagramPacket(respoBytes, respoBytes.length, client, port);
clientSocket.send(sendPacket);
Print out the sequence of bytes before sending, and after receiving. This will tell you if they are identical. Then inspect the bytes corresponding to e.g. an int, and you will immediately see if they are in the correct order or not.
It's hard to be more specific, since you're not showing the sending code.

Categories