Decode UDP message (from Erlang to Java) - java

I just tried to send a message by UDP from an Erlang server to a Java client. Now I am wondering how I should do to interpret this message to something useful.
Here is what I wrote in Erlang:
{ok, Socket} = gen_udp:open(8789, [binary, {active, true}]).
gen_udp:send(Socket, {127,0,0,1},11001, "yeah!").
And here is my Java code:
public class Server {
private DatagramSocket socket;
private byte[] buffer;
public Server() {
try {
socket = new DatagramSocket(11001);
} catch (SocketException e) {
e.printStackTrace();
}
buffer = new byte[65508];
}
public void receivePackage() {
try {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
socket.receive(packet);
byte[] buffer = packet.getData();
System.out.println(buffer);
} catch (IOException e) {
e.printStackTrace();
}
}
}
How do I handle the byte buffer and translate it to something that I can output in the Java console?

on the Erlang side try to send
binary instead of string :
gen_udp:send(Socket, {127,0,0,1},11001, <<"yeah!">>).
On java side:
byte[] b1 = new byte[] {#your byte array};
String s2 = new String(b1);
This will parse binary data to string.

Related

Java string comparison with equals() not working as expected with UDP

I am trying to send a message over UDP and comparing it with a string literal, but it does not seem to work.
Here is the UDP server code
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Controller {
public static void main(String args[]) {
//create UDP server
try {
DatagramSocket socket = new DatagramSocket(5002);
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
//wait for done message
socket.receive(packet);
String msg = new String (packet.getData());
if(msg.equals("Done"))
{
System.out.println("Done received");
}
else {
System.out.println("Done not received");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
And here is the UDP client code
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
public class Slave {
public static void main(String args[]) {
//create UDP client
try {
DatagramSocket socket = new DatagramSocket();
byte[] buffer;
//send Done message
buffer = "Done".getBytes();
DatagramPacket packet = new DatagramPacket(buffer, buffer.length, InetAddress.getLocalHost(), 5002);
socket.send(packet);
} catch (Exception e) {
e.printStackTrace();
}
}
}
The output I get is "done not received", even though done message is sent. What is wrong with the code?
The problem is, that you are declaring a buffer with 1024 bytes, which you are the converting to a string. That string does not equal "Done", it is simply "too long". You have to obtain the actual length of your sent data. You could do something like this in your Controller:
public class Controller {
public static void main(String args[]) {
//create UDP server
try {
DatagramSocket socket = new DatagramSocket(5002);
byte[] buffer = new byte[1024];
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
//wait for done message
socket.receive(packet);
//Get actual data length and copy it
byte[] data = new byte[packet.getLength()];
System.arraycopy(packet.getData(), packet.getOffset(), data, 0, packet.getLength());
//Create string from actual data
String msg = new String (data);
if(msg.equals("Done"))
{
System.out.println("Done received");
}
else {
System.out.println("Done not received");
}
} catch (Exception e) {
e.printStackTrace();
}
}
}
String msg = new String(packet.getData(), packet.getOffset(), packet.getLength());
DatagramPacket contains other information such as the port and host. Calling new String() on the data will extract more information than just the data message. Using packet.getData() and setting the offset will make sure that you extract just the data in the packet and leave out the port and host.
See the JavaDocs for DatagramPacket for more information.
When I debug your code, I can see that the message is "Done" with a lot of following '\u0000' which seems to be a unicode represantation of 0
So you either remove the zeros or you change your if statement to
msg.startsWith("Done")

Java UDP packet only holds 5 bites

The following code is used to send over a simple string in the following formart "address,porttNum".
Here is the client side:
ByteArrayInputStream bin = new ByteArrayInputStream(packet.getData());
DataInputStream dis = new DataInputStream(bin);
try {
System.out.println("Data in packet: " + dis.readLine());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
Here is the server side:
byte[] sbuf = data.getBytes();
// sbuf = output.getBytes();
packet = new DatagramPacket(sbuf,
sbuf.length, packet.getAddress(), packet.getPort());
try {
socket = new DatagramSocket();
socket.send(packet);
} catch (Exception e) {
e.printStackTrace();
}
Say the server sends "abcdefghi", the client only recieves "abcde". I have tried it with multiple test cases and the client always recieves 5 bytes. Can anyone point out where I messed up?
edit:
For debugging purposes I even added the following:
try {
System.out.println("Data in packet: " + dis.readLine());
} catch (IOException e1) {
// TODO Auto-generated catch block
e1.printStackTrace();
}
which outputs the right data the client still does not get it.
edit 2:
I changed the client side to the following:
String data = new String(packet.getData(), StandardCharsets.UTF_8);
System.out.println("Data in packet: " + data);
It makes no difference.
Here is some example code showing construction of a Datagram packet from the bytes of a String, sending it, and reconstruction of the String.
Notice that the buffer for receiving a packet is created much larger than the message that is eventually received. This is necessary as the the UDP socket will truncate the message to the size of the buffer if it receives a message larger than the buffer. For example, if the client sent the message "ZYXWV" to the server, and only created the buffer large enough for that message, and then reused the buffer for the incoming message, only the first 5 characters of the incoming message would be received.
public class DataGram {
public static void main(String[] args) throws SocketException {
new Thread(new Client()).start();
new Thread(new Server()).start();
}
static class Client implements Runnable {
DatagramSocket socket;
Client() throws SocketException {
socket = new DatagramSocket(1234);
}
#Override
public void run() {
byte[] buf = new byte[1024];
DatagramPacket packet = new DatagramPacket(buf, buf.length);
try {
try {
socket.receive(packet);
String msg = new String(packet.getData());
System.out.println(msg);
} finally {
socket.close();
}
} catch (IOException e) {
e.printStackTrace();
}
}
}
static class Server implements Runnable {
#Override
public void run() {
SocketAddress address = new InetSocketAddress("localhost", 1234);
try (DatagramSocket socket = new DatagramSocket()) {
String msg = "abcdefghi";
byte[] buf = msg.getBytes();
DatagramPacket packet = new DatagramPacket(buf, buf.length, address);
socket.send(packet);
} catch (IOException e) {
e.printStackTrace();
}
}
}
}
No DataInputStream or ByteArrayInputStream is used here, since you can directly convert a String to byte[] and back again.

How to send Vector over UDP conection in JAVA

I am trying to send vector object from UDP server to UDP client in Java.
Sending and Receiving string as an object after serializing has been achieved , but I am unable to send or receive vectors. Below is server ide code.
public class UDPReceive {
public UDPReceive() throws IOException {
try {
int port = Integer.parseInt("1233");
int allReceived=0;
String[] custData=new String[3];
DatagramSocket dsocket = new DatagramSocket(port);
byte[] buffer = new byte[2048];
for(;;) {
DatagramPacket packet = new DatagramPacket(buffer, buffer.length);
dsocket.receive(packet);
String msg = new String(buffer, 0, packet.getLength());
String msg2 = new String(packet.getData());
custData[allReceived]=msg;
allReceived++;
if(allReceived == 3){
System.out.println("All Data Received");
for(int i=0;i<3;i++){
System.out.println(custData[i]);
}
Vector rawData=getTransactions(custData[0],custData[1],custData[2]);
System.out.println("Vectot size "+ rawData.size());
byte[] sendData = new byte[1024];
sendData=(object[])rawData.toArray();
allReceived=0;
}/*if ends here */
}
}
catch (Exception e) {
System.err.println(e);
}
}
Here I want to send back "rawData" variable to client and receive it, and covert it to vector in client side. I tried using byte[] as well, but it didn't work
I suggest you serialize the Vector as an ObjectOutputStream and use ObjectInputStream to get the original Vector.
public static byte[] objectToBytes(Object o) throws IOException {
ByteArrayOutputStream baos = new ByteArrayOutputStream();
ObjectOutputStream oos = new ObjectOutputStream(baos);
oos.writeObject(o);
oos.close();
return baos.toByteArray();
}
to reverse
public static <T> T bytesToObject(byte[] bytes) throws IOException, ClassNotFoundException {
return (T) new ObjectInputStream(new ByteArrayInputStream(bytes)).readObject();
}

Socket Client Sends nothing

I have a Problem: I have a Socket Client on my Android Phone and a Java Socket Server on my PC. Server -> Android works perfektly, but Android -> Server doesn't work.
This is my sending Method on my Phone:
public void sendMessage(String cmd, String parameter) {
String msg;
if(!parameter.equals(""))
msg = cmd+";"+parameter;
else
msg = cmd+";null";
Log.v(TAG,"Send: "+msg);
DataOutputStream bos;
try {
bos = new DataOutputStream(s.getOutputStream());
bos.write(msg.getBytes("US_ASCII"));
bos.flush();
} catch (IOException e) {
e.printStackTrace();
}
}
And this is The receiving on my Server:
#Override
public void run() {
while (isRunning) {
try {
DataInputStream dis = new DataInputStream(s.getInputStream());
String message = dis.readUTF();
System.out.println("#"+this.ID+": Received: "+message);
obs.setID(ID);
obs.proceedMsg(message);
} catch (IOException ex) {
this.isRunning = false;
System.out.println("#"+this.ID+": Closed Instance");
}
}
}
Has anyone an Idea? :)
Thanks
You should use writeUTF on a client side. Your server is expecting UTF as you use readUTF method.
writeUTF writes additional 2 bytes in the beginning which indicate block length. When you use plain write method, you do not supply those bytes and this is the problem.

Receiving byte array over a socket

i have a program which accepts connection from a phone that sends a byte array, i am able to test the connection when it is made , however how do i know that i am actually receiving something? how can i "see" if any thing is being sent over the socket. Because from my code below i am not able to have the resulting file "saved.jpg" created. Does this mean that it did not receive anything?
public class wpsServer {
//vars
private int svrPort = 3334;
private ServerSocket serverSocket;
private Image image = null;
public wpsServer()
{
try {
serverSocket = new ServerSocket(svrPort);
System.out.println("Server started on "+svrPort);
}
catch (IOException e) {
System.out.println("Could not listen on port: "+svrPort);
System.exit(-1);
}
}
public void listenForClient()
{
Socket clientSocket = null;
try {
clientSocket = serverSocket.accept();
if(clientSocket.isConnected())
System.out.println("Connected");
byte[] pic = getPicture(clientSocket.getInputStream());
InputStream in = new ByteArrayInputStream(pic);
BufferedImage image = ImageIO.read(in);
File outputfile = new File("saved.jpg");
ImageIO.write(image, "jpg", outputfile);
}
catch (IOException e) {
System.out.println("Accept failed: "+svrPort);
System.exit(-1);
}
}
public byte[] getPicture(InputStream in) {
try {
ByteArrayOutputStream out = new ByteArrayOutputStream();
byte[] data = new byte[1024];
int length = 0;
while ((length = in.read(data))!=-1) {
out.write(data,0,length);
}
return out.toByteArray();
} catch(IOException ioe) {
//handle it
}
return null;
}
}
The in.read call will only return -1 if the other end closes the socket. While the socket is alive, that call will block until more data is available.
What you need to do is change your "protocol": the client should send the array size first, then the data. The server should read that length, and stop reading the file when that's done (go back to waiting for the next file for instance).

Categories

Resources