1

I'm currently experimenting with UDP-Communication between a server written in Python using the SocketServer class and a client written in Java using the DatagramSocket and DatagramPacket classes. The server accepts python method calls as an input and routes the stdout and stderr back to the client, transmitted in a 1024byte sized packet.

The communication is working, the client can receive packets from the server and send packets to it, however I'm running into problems when comparing data.

For example, when receiving a packet containing the string __DONE__\n in the client, it prints fine using System.out.print(packet.getData()). I'm only running into problems when I am trying to compare it to a String done = "__DONE__\n" as follows:

while (String(packet.getData()).equals(done) != true) {
    doStuff();
}

Here the loop runs forever, as the evaluated statement always returns false. My guess is that it has something to do with different encodings. I tried to compare the byte-arrays of both the string from the packet and the native Java string and got these results:

String done:                5f5f444f4e455f5f0a
String(packet.getData()):   5f5f444f4e455f5fa0000000[...]
// The 0s are repeated for the whole 1024bytes of the packet

It seems that the String from the datapacket contains the bytes I'm trying to compare as well as the other bytes from the 1024byte packet, which is why the String.equals() method always returns false.

Is there a way to force Java to omit the trailing zeros when converting from a byte array to a String?

jbaiter
  • 6,913
  • 4
  • 30
  • 40

3 Answers3

2

I now managed to resolve the issue by specifyng an offset of 0 and the length of the packet when converting my packet to a String:

String(packet.getData(), 0, packet.getLength(), "UTF-8");

The resulting String is stripped of the trailing 0s.

jbaiter
  • 6,913
  • 4
  • 30
  • 40
0

It would seem to me that you can use the setLength before packet.getData to specify how many bytes you want to get from the buffer.

http://download.oracle.com/javase/1.4.2/docs/api/java/net/DatagramPacket.html#setLength%28%29

Matti Lyra
  • 12,828
  • 8
  • 49
  • 67
  • Please consider these possibilities: (0) the OP doesn't know in generality how many bytes he wants to get (1) setLength is something the SENDER might want to do (2) the RECEIVER (the Java code with the problem) might want to use getLength (3) using getLength is quite likely to return 1024, according to the OP – John Machin Feb 01 '11 at 00:10
0

5f5f444f4e455f5fa is an ODD number of hex characters. Looks like it should be 5f5f444f4e455f5fa0 i.e. "__DONE__\xA0" rather than the "__DONE__" that you wrote. If not, why is that 'a0' in the incoming packet?

Isn't sending a 1024-byte packet padded out with NULs a bit wasteful? Perhaps you should be talking to the source of the packets.

John Machin
  • 81,303
  • 11
  • 141
  • 189
  • Oh my, yes, thank you for the correction, the messages do indeed end with a newline. I edited my original post. Sorry! – jbaiter Jan 31 '11 at 23:39
  • @JeanMarieStaub: Your post is still not consistent. Your hex for your `done` string still has an ODD number of hex characters. Your hex output for the packet shows `a0` (a NO-BREAK SPACE) not `0a` (a newline). PLEASE copy/paste from actual output, don't type from memory. – John Machin Jan 31 '11 at 23:59
  • The two hex-representations are actually taken from my terminal output. I generated them by parsing through the strings' byte arrays and adding together the `format("%x", byte)` string for each byte, maybe that's where the inconsistency is coming from. I removed nothing manually from my output, except for the last couple of hundred 0s from the second string. As for your second suggestion, I am probably going to look into that, however the server code was not written by me and at the moment I'm just trying to get a very rudimentary experimental version working to experiment with. – jbaiter Feb 01 '11 at 00:10
  • @JeanMarieStaub: aarrgghh (1) try "%02x " [leading zero, space separator for legibility] (2) Doesn't Java have an equivalent of Python's repr()? [reinventing the wheel as a polygon of few sides is not a good idea] – John Machin Feb 01 '11 at 00:16
  • Sorry for the teethgrinding-inducing mistake, I'm only taking my very first steps with Java and this was a quick and dirty hack to see the byte representation of the strings as I didn't find an equivalent of repr() in Java (and according to http://stackoverflow.com/questions/1350397/java-equivalent-of-python-repr it doesn't seem to exist in the standard library). Although that's no excuse for that particular mistake, the format syntax is almost the same as in Python and C :-) After correcting it, the output is indeed `5f5f444f4e455f5f0a`, not `[..]fa` as previously. – jbaiter Feb 01 '11 at 00:29
  • On a different note, I worked around the issue now by calling "startsWith(done)" instead of "equals()". It's not as water-tight, but as far as I can judge from the server code the "__DONE__\n" message is always issued as a single packet, so there shouldn't be any uncertainty. The original question remains interesting on a more general level, though. – jbaiter Feb 01 '11 at 00:33
  • More generally: do the Java equivalent of `packet_string = packet_string`.rstrip('\x00')`. Even better: write your client in Python :-) – John Machin Feb 01 '11 at 00:50
  • As there doesn't seem to be an equivalent of rstrip for byte[] in Java (at least according to my last 10 minutes of googling), I guess I'll write my own helper. Thanks for all the helpful advice! I would do it in Python, if I could. The thing is that I'm trying to write an Android application that talks to a local (non-gui python scripts work quite well under android) server to do the heavy lifting and give the results back to the frontend. I don't see myself porting the 4k+ lines of code of the backend to Java with my present level :-) – jbaiter Feb 01 '11 at 00:59