user1150445
user1150445

Reputation: 21

Decode "send" message from WebSocket with Java

I'm trying to write my own WebSocket Server.

I know that there are some frameworks for this but i would like to learn, so I do it on my own :)

My JavaScript client reacts currently with onOpen, so I think the handshake is valid and the connection is established.

Now the problem:

My Java server uses a selector thread for reading on an Channel.

If I do *.send("test message") on the WebSocket object at my client, my server can't decode the byte array.

I found no information about the used encode/decode technology, so I tried many versions to decode.

for example:

new String(Base64.decodeBase64(buffer.array()))

or

Charset set = Charset.forName("UTF-8");
new String(Base64.decodeBase64(set.decode(buffer).toString()))

The message is completely read from the Channel into an ByteBuffer, so I don't think this is the problem.

Can anyone help me?


okay this Post helps me to send data to the Client. This works fine :)
But I don't understand how to decode the data received from the Client :(

At the Client i send only one Letter

socket.send("x");

The Server receives 7 byte ???

ByteBuffer buffer = ByteBuffer.allocate(8192);
int read = client.getInputStream().read(buffer2.array());
System.out.println("read: " + read);

// read: 7

for (int i = 0; i < read; i++) {
  int j = buffer.get(i) & 0xff;
  System.out.println("i: " + i + " => " + j + "=>" + new BigInteger(j + "").toString(2));
}

//i: 0 => 129=>10000001
//i: 1 => 129=>10000001
//i: 2 => 195=>11000011
//i: 3 => 235=>11101011
//i: 4 => 4=>100
//i: 5 => 96=>1100000
//i: 6 => 187=>10111011

If i do this

secondByte AND 0111 1111

the result of (i: 1) is "1" i think this means that there are only one byte data. Then why read is 7 ???

Upvotes: 2

Views: 4640

Answers (2)

private String decodeMessage(){
    try {
        byte[] data = new byte[1024];
        int size = in.read(data);
        if (size == -1) return null;
        byte[] decoded = new byte[size-6];
        byte[] key = new byte[]{ data[2], data[3], data[4], data[5] };
        for (int i = 0; i < size-6; i++) {
            decoded[i] = (byte) (data[i+6] ^ key[i & 0x3]);
        }
        return new String(decoded, "UTF-8");
    }catch (IOException ex){
        ex.printStackTrace();
    }
    return "ping";
}

This code is probably bad, but it works for me

Upvotes: 2

pimvdb
pimvdb

Reputation: 154818

As for your second issue - the data from client to server is always masked as I also explained at the link above. Masks take 4 bytes.

So, the length of the actual data is indeed 1. Only the last 7 bits of the second byte say something about the length - the first bit doesn't, so just discard that one to get 000 0001 which is 1.

The bytes are categorised as follows in this case:

  • 0, 1 are meta bytes
  • 3, 4, 5, 6 are masks
  • 7 is the data

To get the data, calculate data XOR masks[data_index MOD 4], i.e. 187 XOR 195 in this case, which is 120 - the character code for x.

Upvotes: 2

Related Questions