I have persistent problems with networking in java. It might because I'm used to operate upon bytes, which are for some reason signed in Java (I take it as a proof of existence of the ultimate Evil).
I have been struggling to send binary data using some packet system. Originally, I wanted to create data myself, but Java is not designed to operate with bytes. Instead, it's advised that you send serialised object.
So I looked up how to create a serialisable class ChatPacket
that I will send over network.
This my code derived from answer similar to the one I linked above (I couldn't found the original one):
//Convert packet to raw data
public byte[] getBytes() {
ByteArrayOutputStream bos = new ByteArrayOutputStream();
ObjectOutput out = null;
try {
//Pass the stream refference to the weird object output stream thing
out = new ObjectOutputStream(bos);
//Save the packet into byte stream
out.writeObject(this);
//Create separate arrays of bytes
byte[] data = bos.toByteArray();
//Funny way to convert int in array of 4 bytes. The Java Way...
byte[] size = ByteBuffer.allocate(4).putInt(data.length).array();
//The final data array - feel free to sugest more efficient way to merge the two arrays
byte[] data_all = new byte[data.length+4];
//Merge the arrays of bytes - I found no other way than creating third array.
for(int i=0; i<data_all.length; i++) {
//Save the size
if(i<4) {
data_all[i] = size[i];
}
//Save the data
else {
data_all[i] = data[i-4];
}
}
//Debug output
Log.debug("Sending packet of "+data.length+" bytes");
for(int i=0; i<data_all.length; i++) {
Log.debug(i+": Sending character: "+((char)data_all[i]))+" ["+(int)data_all[i]+"]");
}
Now the last debug lines produce a nice output:
Sending packet of 262 bytes
0: Sending character: 0 [0] -
1: Sending character: 0 [0] | The int - size of the packet
2: Sending character: 1 [1] |
3: Sending character: 6 [6] -
4: Sending character: -84 [-84] -
5: Sending character: -19 [-19] |
6: Sending character: 0 [0] | The data generated within the serialisation function
7: Sending character: 5 [5] |
8: Sending character: 115 [115] |
9: Sending character: 114 [114] ...
10: ...
There are numbers instead of actual chars. Forgive me that - I have fixed the function after adding the code and was lazy to rewrite it.
So far so good. Now let's see what arrives on the other side. I'm receiving data within a loop where I'm calling read method upon some buffered stream:
while((character=in.read())!=-1)
...
I have created a very similar output to the one you can see above, just that it now prints the data received.
1: Received character: \0 [0] -
2: Received character: \0 [0] | The size again
3: Received character: [1] |
4: Received character: [6] -
Expecting 262 bytes of data! -
1: Received character: � [65533] |
2: Received character: � [65533] | The serialised data...
3: Received character: \0 [0] |
4: Received character: [5] ...
5: ...
As you can see, instead of overflowing or something like that, the negative numbers have somehow turned into huge values.
I can's see what's actually being sent over the network - I've been already asking about that but the answer really didn't help, as you can see.
Basically my question regarding this is now:
- How is it possible, that the negative values can pass over the network as bytes - unless they are already broken when sent...
- How can I receive such values - the values in debug above are returned by
read
method...
In the end, I need to recontsruct the byte array back. So also I need to have values thich can be looselesly converted into bytes.
private List<Byte> buffer = new ArrayList<>();
public boolean receiveChar(int current) {
buffer.add((byte)current);
... some stuff
}