TooTallNate / Java-WebSocket

A barebones WebSocket client and server implementation written in 100% Java.
http://tootallnate.github.io/Java-WebSocket
MIT License
10.36k stars 2.57k forks source link

WebSocket server fails to properly handle hexadecimal data from clients #1429

Open dlaoy opened 3 days ago

dlaoy commented 3 days ago

Describe the bug I have encountered an issue with my Android WebSocket server where it fails to correctly handle hexadecimal data sent from clients.

//java
//function
public byte[] hexStringToByteArray(String s) {
        int len = s.length();
        if (len % 2 != 0) {
            throw new IllegalArgumentException("Hex string must have an even length");
        }
        byte[] data = new byte[len / 2];
        for (int i = 0; i < len; i += 2) {
            data[i / 2] = (byte) ((Character.digit(s.charAt(i), 16) << 4)
                    + Character.digit(s.charAt(i+1), 16));
        }
        return data;
    }

 @Override
    public void onMessage(WebSocket conn, ByteBuffer message) {
        //Log.d("websocket", "onMessage() Listen ByteBuffer data->"+ByteUtil.byteBufferToString(message));

        byte[] bytes = new byte[message.remaining()];
        message.get(bytes);

        Log.d("websocket", "onMessage() Listen ByteBuffer data->"+byteArrayToHexString(bytes));
        res.post(new Runnable() {
            @Override
            public void run() {
                res.setText("Byte Listen:"+byteArrayToHexString(bytes));
            }
        });
    }
//python socketClient
import asyncio
import websockets

async def send_byte_array():
    uri = "ws://192.168.0.102:9093"
    byte_data = bytes([0x02, 0x47, 0x00, 0xda, 0x5d, 0x4f, 0xf2, 0x02]) /// my byte

    async with websockets.connect(uri) as websocket:
        await websocket.send(byte_data)
        print("Sent byte data:", byte_data.hex())

async def receive_byte_array():
    uri = "ws://192.168.0.102:9093"  

    async with websockets.connect(uri) as websocket:
        while True:
            byte_data = await websocket.recv() 
            hex_string = byte_data.hex()
            print("Received byte data:", hex_string)

async def main():
    await asyncio.gather(send_byte_array(), receive_byte_array())

asyncio.get_event_loop().run_until_complete(main())

When running the Android WebSocket server and subsequently starting Python to send socket messages, the sent and received data do not match.

1719899969523

PhilipRoman commented 2 days ago

I will check this when I get back home but I can tell you there is a 99% chance the issue is in your own code, not the library.

Please post your implementation of byteArrayToHexString also

dlaoy commented 2 days ago

byteArrayToHexString

public static String byteArrayToHexString(byte[] bytes) {
StringBuilder sb = new StringBuilder();
for (byte b : bytes) {
sb.append(String.format("%02X", b));
}
return sb.toString();
}

This is my byteArrayToHexString method

dlaoy commented 2 days ago

OK,I konw.This problem has been bothering me for a week. The position in the ByteBuffer object is in position 4, causing it to be read starting from position 4. For example: bytes([0x02, 0x03, 0x06, 0x05]) -- position=0 bytes([0x02, 0x47, 0x00, 0xda, 0x5d, 0x4f, 0xf2, 0x02]) -- position=4 bytes([0x02, 0x47, 0x00, 0xda]) -- position=4 bytes([0x02, 0x47, 0x00, 0x06, 0x3f, 0x4d, 0xf9, 0x02]) -- position=7 bytes([0x02, 0x03, 0x00, 0x06, 0x02, 0x02, 0x02, 0x02]) -- position=0 bytes([0x02, 0xf9, 0x00, 0x06, 0x02, 0x02, 0x02]) -- position=2

My solution is:

@Override
    public void onMessage(WebSocket conn, ByteBuffer message) {
        //Log.d("websocket", "onMessage() Listen ByteBuffer data->"+ByteUtil.byteBufferToString(message));
        ByteBuffer messageCopy =message;
        messageCopy.position(0);                /// set the position on zero

        byte[] bytes = new byte[messageCopy.remaining()];
        messageCopy.get(bytes);
        sendToAllBytes(bytes);

        Log.d("websocket", "onMessage() Listen ByteBuffer data->"+ByteUtil.byteArrayToHexString(bytes));
        res.post(new Runnable() {
            @Override
            public void run() {
                res.setText("Byte Listen:"+ByteUtil.byteArrayToHexString(bytes));
            }
        });
    }

The version I am using is implementation group: 'org. java websocket', name: 'Java-WebSocket', version: '1.5.6'

PhilipRoman commented 2 days ago

Interesting, I would consider this a bug in the library. I noticed there are some inconsistencies with how ByteBuffer position/limit is handled by different functions, I guess we should go over API functions and add documentation or fix them.