1

So I am using SocketChannels in java to send and receive data for a project. The project interacts with a 3rd party who require a ByteBuffer of the data but which is prefixed with 4 bytes which is its length.

When receiving I will receive a ByteBuffer which I need to deconstruct the 4 byte length from the front and extract the data. The messages I receive are not fixed length.

My current implementation is as follows:

public PedResponse send(ByteBuffer message) {
        String returnString;
        try {

            message.flip();

            while (message.hasRemaining()) {
                socketChannel.write(message);
            }

            ByteBuffer readBuffer = ByteBuffer.allocate(5000);
            int bufferSize = socketChannel.read(readBuffer);
            if (bufferSize == -1) {
                socketChannel.close();
            } else {
                readBuffer.flip();
            }

            returnString = new String(deconstructMessage(readBuffer.array()), "UTF-8").trim();

            response = parser.parseResponse(returnString);

        } catch (IOException e) {
            e.printStackTrace();
        }
        return response;
    }

private ByteBuffer constructMessage(byte[] data) {

        // Construct a buffer where we'll put the data to send
        ByteBuffer sendBuffer = ByteBuffer.allocate(4 + data.length);

        // it's the default, but included for clarity
        sendBuffer.order(ByteOrder.BIG_ENDIAN);

        // Put the 4-byte length, then the data
        sendBuffer.putInt(data.length);
        sendBuffer.put(data);

        // Extract the actual bytes from our sendBuffer
        return sendBuffer;
    } 

public byte[] deconstructMessage(byte[] data) {

        byte[] filteredByteArray = Arrays.copyOfRange(data, 4, data.length - 4);

        return filteredByteArray;
    }

//Currently not being used.
private byte[] deconstructMessage(byte[] data) {

        // Construct a buffer where we'll put the data to send
        ByteBuffer receiveBuffer = ByteBuffer.allocate(data.length);

        // it's the default, but included for clarity
        receiveBuffer.order(ByteOrder.BIG_ENDIAN);

        // Get the 4-byte length, then the data
        receiveBuffer.getInt(data.length);
        receiveBuffer.get(data);

        // Extract the actual bytes from our receivedBuffer
        byte[] dataReceived = receiveBuffer.array();
        return dataReceived;
    }

So as you can see, I am creating a new ByteBuffer with the size of 5000, but ideally I don't want to do this. So the question I have, is how can I not use this oversized ByteBuffer, but instead just read the data I received, so I can use my unused deconstruct message method?

James King
  • 2,425
  • 7
  • 30
  • 45

1 Answers1

0

ByteBuffer has method get() and it returns byte from the current position. So, you can read 4 bytes first and get the size.

Vitaly
  • 2,552
  • 2
  • 18
  • 21
  • so in the send method, I create a new ByteBuffer called readBuffer. So ideally I want to get rid of that. Whats my best option – James King Dec 15 '16 at 11:37
  • as far as I know there is no unwrap() method in ByteBuffer. Anyway you need your own byte[] to copy data from the buffer – Vitaly Dec 15 '16 at 11:46
  • and instead of 5000 you can use method remaining() – Vitaly Dec 15 '16 at 11:48
  • Sorry, slightly confused with this, so I'm guessing I need to do something like this:?? ByteBuffer buffer = null; buffer.position(0); buffer.limit(1); while (buffer.hasRemaining()) { socketChannel.read(buffer); } buffer.rewind(); – James King Dec 15 '16 at 12:05
  • http://stackoverflow.com/questions/1396016/how-to-initialize-a-bytebuffer-if-you-dont-know-how-many-bytes-to-allocate-befo ...check this link it might help you out – OlaB Dec 15 '16 at 12:10