1

First off forgive me if I am mistaken for how blocking works, to my understanding blocking will pause the thread until it is ready, for exsample when reading user input the program will wait until the user hits return.

My problem is that instead of waiting for data to become available it reads bytes with the value 0. Is there a way to block until data becoms available?

The method readBytes is called in a loop.

public byte[] readBytes(){
  try{

     //read the head int that will be 4 bytes telling the number of bytes that follow containing data
     byte[] rawLen = new byte[4];
     socketReader.read(rawLen);
     ByteBuffer bb = ByteBuffer.wrap(rawLen);
     int len = bb.getInt();

     byte[] data = new byte[len];
     if (len > 0) {
        socketReader.readFully(data);
     }

     return data;

  } catch (Exception e){
     e.printStackTrace();
     logError("Failed to read data: " + socket.toString());
     return null;
  }
}
user2131323
  • 105
  • 10
  • a Stream that extends `InputStream` **will** block on `read` see https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#read() `readFully` also blocks - maybe the server is sending zeros – Scary Wombat Jul 20 '17 at 01:42
  • You will have to forgive me here, as this is my first time with sockets. I have tried using the following as the reader and the result is the same. InputStream socketReaderStream = socket.getInputStream(); – user2131323 Jul 20 '17 at 01:47
  • Your use of `read()` might not read all 4 bytes. Did you mean to use `readFully()` there to ensure that you read all 4 bytes? The return value of `read()` is the actual number of bytes read. – ck1 Jul 20 '17 at 01:48
  • Your question is fine. What type of Object is `socketReaderStream` ? – Scary Wombat Jul 20 '17 at 01:49
  • All 4 bytes get the value 0 even when there is no data available, is there a way to make it wait until data is availble, it says read should block but I am struggling with getting it to work. – user2131323 Jul 20 '17 at 01:50
  • Here you go Wombat, this is the instance variables: private InputStream socketReaderStream; private OutputStream socketWriterStream; private DataOutputStream socketWriter; private DataInputStream socketReader; – user2131323 Jul 20 '17 at 01:51
  • 1
    try changing to `int br = socketReader.read(rawLen); System.out.println ("Bytes read " + br);` (for debug) – Scary Wombat Jul 20 '17 at 01:54
  • Printed -1 to the console – user2131323 Jul 20 '17 at 01:55

1 Answers1

2

If read() returned -1, the peer has disconnected. You aren't handling that case. If you detect end of stream you must close the connection and stop reading. At present you have no way of doing so. You need to reconsider your method signature.

You should use readInt() instead of those four lines of code that read the length. At present you are assuming have read four bytes without actually checking. readInt() will check for you.

This way also you will never get out of sync with the sender, which at present is a serious risk.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • it used to be readInt(), same thing happened, also tried readFully – user2131323 Jul 20 '17 at 01:57
  • The same thing as what? As `read()` returning -1? Impossible. – user207421 Jul 20 '17 at 01:58
  • Not the -1, sorry should have been more clear, same reading nothing, im checking now though if the connection is still active, the server doesnt say its lost connection – user2131323 Jul 20 '17 at 02:00
  • As I already stated in my answer, you aren't handling end of stream correctly. If `readInt()` encounters end of stream, it wil row `EOFException`. So will `readFully()`. – user207421 Jul 20 '17 at 02:02
  • Yep the server was closign the connection but not reporting it. Thank you all for the help – user2131323 Jul 20 '17 at 02:02
  • @user207421 you say "This way also you will never get out of sync with the sender, which at present is a serious risk." what do you mean? why is there a risk getting out of sync with his method? – yeahman Jan 12 '20 at 19:50