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.
Related
I have a java program written that simply receives data sent through a UDP socket and prints it to the screen. The data that is received is sent from another computer that uses matlab to send the data. I am pretty sure that the matlab simulation is fine because all it does is take a constant value of 2 with a double data type, uses a byte packer to pack the data and sends it through a UDP block to the specified IP Address and port. I concurrently run the java code on another pc which receives the data packet as a byte array of length 1024.
The data is received just fine, however the value that is constantly printed is
4.7783097267364807 E -299.
I am not sure if my code is grabbing the desired data from the packet correctly or if the ByteBuffer.wrap(.....).getDouble() function is used correctly. Any help would be greatly appreciated
import java.io.*;
import java.net.*;
import java.nio.ByteBuffer;
class receiver
{
public static void main(String args[]) throws Exception
{
DatagramSocket serverSocket = new DatagramSocket(1024);
byte[] receiveData = new byte[1024];
byte[] sendData = new byte[1024];
System.out.println("Listening...");
while(true)
{
DatagramPacket receivePacket = new DatagramPacket(receiveData, receiveData.length);
serverSocket.receive(receivePacket);
double data = ByteBuffer.wrap(receiveData).getDouble();
System.out.println(data);
}
}
}
Your code is correct given the specification, but Matlab is sending you 0x0200000000000000 (or something shorter: see below). The big-endian representation of 2.0 as a double is 0x4000000000000000, so they are certainly not sending you a double.
To get 2 from what they're actually sending you, do this:
ByteBuffer bb = ByteBuffer.wrap(receivePacket.getData(), 0, receivePacket.getLength());
bb.order(ByteOrder.LITTLE_ENDIAN);
Then try the following, separately, in this order, until one works:
long l = bb.getLong();
int i = bb.getInt();
short s = bb.getShort();
byte b = bb.getByte();
without a buffer underflow. The way you're wrapping the buffer you are ignoring the datagram length, so it is impossible to tell whether they are sending one, two, four, or eight bytes.
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);
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
I'm writing a UDP Client to transfer a file to a UDP server. First I try to measure the length of the file, devided by the buffer length to be sent in UDP packet, to get the number of packets required to be sent. I send this number to the server first to acknowledge it. But on the server side, the transform from byte array of the receiving packet into the initial number just failed. Can anyone help me out of this? Here is my code on the client side:
DatagramSocket socket=new DatagramSocket();
File f = new File(filename);
long fileSize = f.length();
byte[] buffer = new byte[16384];
long packetNumber = (fileSize/(buffer.length))+1;
DatagramPacket sendPacket=new DatagramPacket(buffer,buffer.length,addr,srvPort);
String str=Long.toString(packetNumber);
buffer = str.getBytes();
socket.send(sendPacket);
And here is the code on the server side:
DatagramSocket socket=new DatagramSocket(port);
byte[] buffer=new byte[16384];
DatagramPacket receivePacket=new DatagramPacket(buffer, buffer.length);
while(true)
{
socket.receive(receivePacket);
if (receivePacket.getData().toString().trim()!=null)
{
String str=receivePacket.getData().toString();
System.out.println(str);
long pcount=Long.parseLong(str);
System.out.println(pcount+" packets to be received.");
break;
}
}
But on the server side the variable pcount can always not be resolved, and when I try to print out the str, it writes out some "[B#60991f" or sth, weird.
This code doesn't make any sense.
Most networks won't let you send a datagram over 534 bytes reliably.
At present you are sending 16384 bytes of zero value, because you aren't putting anything into the buffer: instead you are creating a new buffer after creating the DatagramPacket. So you aren't sending anything yet.
And you aren't receiving anything yet either. The result of String.trim() cannot be null. You must reset the byte array in a DatagramPacket before every receive(), because it shrinks to the size of the actual received packet, so unless you reset it it keeps getting smaller and smaller. The result of toString() on a byte array does not include its contents, so parsing it is futile.
You need to study several basic Java programming concepts: too many to answer here.
You're receiving a byte array, using toString() won't give you anything.
You should reconstruct the String from the bytes array using new String
Im trying to send a packet back to the user informing them of all the people currently on the server, when they send a message to the server which has the word "who" in it.
Here is my code:
else if( response.contains( "who" ) )
{
System.out.println( "Size of names collection: "+names.size() );
buf = null;
buf = names.toString().getBytes();
int thisPort = packet.getPort();
packet = new DatagramPacket( buf, buf.length,packet.getAddress(),thisPort );
socket.send(packet);
}
The output of the print statement above is 2 indicating that there are two people on, for example andrew and james. Now when I package it up and send it I would expect it to output this:
[Andrew, James]
But instead the client gets:
[Andrew,
And thats it. Whats the problem? BTW I have to use UDP for this and can't switch to TCP
UPDATE
Here is the code in the client class that receives the packets:
while( true )
{
try
{
// Set the buf to 256 to receive data back from same address and port
buf = null;
buf = new byte[256];
packet = new DatagramPacket(buf, buf.length, address, 4445);
socket.receive(packet);
String response = new String( packet.getData() );
// Receive the packet back
System.out.println( response );
}
catch( IOException e )
{
}
}
Your datagram is being truncated to 256 byes because that's the size of the buffer you declared for the receiving DatagramPacket. If your datagrams can be longer, make the buffer bigger.
Best practice is to make it one bigger than the largest datagram you are expecting to receive. Then if you receive one that size you have an application protocol error.
You should check on both client and server the length of the DatagramPacket after the send/receive operation respectively (with the getLength method) to make sure it's the same, that would be the first hint. What Collection are you using for names?
Your question is incomplete. However..
UDP loses packets. That's why it's not reliable to use UDP for File Transfer purposes. The Adobe RTMFP uses UDP to transfer audio and video data in which many packets are lost., But audio/video content streaming is really faster when compared to TCP. I don't know if this answers your question, I just want to say that UDP does lose packets.