0

I have TCP client which received audio (encoded) data through socket. I have to keep received data in some buffer and provide to decoder when requested by decoder chunk by chunk. Data is in byte[] and array size can vary. What should I use as buffer to keep the received byte[] chunks. I know about BlockingQueue but it doesn't provided adding and retrieving N size of byte[].

Does Java provide any data structure for this purpose, can we use ByteBuffer?

SohailAziz
  • 8,034
  • 6
  • 41
  • 43

1 Answers1

1

Does your client know how the byte array size varies? A well known approach (it needs you manage this also at the server side) is to encapsulate the data inside a packet with the following fields: | TYPE | SIZE | DATA | so, supposing the client has an open socket connection and instantiate a DataInputStream (dataInputStream = new DataInputStream(socket.getInputStream())), the client can read the data in a thread which run method is something like this:

@Override
public void run() {
    while(running) {

        int pckType = readPacketType();

        int pckSize = readPacketSize();

        byte[] data = readPacketContent(pckSize);

        // do something with data
        // you can use Semaphore instances in order to maintains a set of permits if needed
    }
}

where

private int readPacketType() {
    int result = -1;
    byte[] array = new byte[1];
    try {
        dataInputStream.read(array);
        result = (int)array[0];
    } catch (IOException ex) {
        return -1;
    }
    return result;
}

private int readPacketSize() {
    int result = -1;
    byte[] array = new byte[4];
    try {
        dataInputStream.read(array);
        result = ByteBuffer.wrap(array).getInt();
    } catch (IOException ex) {
        return -1;
    }
    return result;
}

private byte[] readPacketContent(int contentSize) {
    byte[] result = new byte[contentSize];
    try {
        dataInputStream.read(result);
    } catch (IOException ex) {}
    return result;
}

noting that I assigned, for example, 1 byte for the TYPE field and 4 byte for the SIZE field

EDIT: You can use an implementation of the BlockingQueue interface like LinkedBlockingQueue. You can put byte[] of different size and retrieve them coherently (keeping the order and the size). Follows an easy check ;)

LinkedBlockingQueue<byte[]> lbq = new LinkedBlockingQueue<byte[]>();
String str1 = "blablabla";
String str2 = "blabla";
try {
    lbq.put(str1.getBytes());
    lbq.put(str2.getBytes());
    lbq.put(str1.getBytes());
} catch (InterruptedException e) {
    e.printStackTrace();
}
byte[] b = null;
int size = lbq.size();
for(int i=0; i<size; i++) {
    try {
        b = lbq.take();
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    System.out.println(b.length);
}
bardi
  • 373
  • 5
  • 17
  • I think I couldn't express my problem correctly. I need to know a data structure which I can use to put received chunks (byte[]) until actually start decoding. Once decoding start, I want to pick those chunks(byte[]) and feed to decoder. I can use BlockingQueue but how can I specify byte[] size when read/writing to queue? – SohailAziz Jun 11 '14 at 12:14
  • sorry, I misunderstood the issue and still don't understand what can fit your needs since I'd use the BlockingQueue instance and feed it with byte[] (of different size) as single objects – bardi Jun 11 '14 at 12:46
  • if I use BlockingQueue, How can I put different size byte[] arrays via put(object) and what size of byte[] will be returned in take(object) ? @bardi – SohailAziz Jun 11 '14 at 12:52
  • `LinkedBlockingQueue lbq = new LinkedBlockingQueue();` `String str1 = "blablabla"; lbq.put(str1.getBytes()); byte[] b1 = null; b1 = lbq.take(); System.out.println(b1.length);` – bardi Jun 11 '14 at 13:17
  • yes, I checked with BlockingQueue. we can put different size byte[] in queue and when dequeuing i.e take(), it returns the byte[] in same length n order as entered. Edit your answer and I'll accept. Thanks for help. – SohailAziz Jun 11 '14 at 14:03