1

I have a Socket connection to an application that I hosted elsewhere. Once I connected I made a OutputStream and DataInputStream.

Once the connection has been made, I use the OutputStream to send out a handshake packet to the application. Once this handshake has been approved, it returns a packet through the DataInputStream (1).

This packet is processed and is returned to the application with the OutputStream.

If this returned data is valid, I get another packet from the DataInputStream (2). However, I have not been able to read this packet through the DataInputStream.

I have tried to use DataInputStream.markSupported() and DataInputStream.mark() but this gave me nothing (except for an empty Exception message).

Is it possible to read the input stream for a second time? And if so, can someone please point me out what I'm doing wrong here?

EDIT: Here is my solution:

// First define the Output and Input streams.
OutputStream output = socket.getOutputStream();
BufferedInputStream bis = new BufferedInputStream(socket.getInputStream());

// Send the first packet to the application.
output.write("test"); // (not actual data that I sent)

// Make an empty byte array and fill it with the first response from the application.
byte[] incoming = new byte[200];
bis.read(incoming); //First packet receive

//Send a second packet to the application.
output.write("test2"); // (not actual data that I sent)

// Mark the Input stream to the length of the first response and reset the stream.
bis.mark(incoming.length);
bis.reset();

// Create a second empty byte array and fill it with the second response from the application.
byte[] incoming2 = new byte[200];
bis.read(incoming2);

I'm not sure if this is the most correct way to do this, but this way it worked for me.

Max
  • 2,354
  • 2
  • 14
  • 27
  • 1
    Please see http://stackoverflow.com/questions/9501237/read-stream-twice – akashpandey Feb 08 '16 at 13:46
  • A much better solution is to remember anything you need to remember and only ever read once. – Peter Lawrey Feb 08 '16 at 13:51
  • That is my problem. I don't get everything in the first read. I get a second (and third) response from the application after I submitted a packet from the `OutputStream`. – Max Feb 08 '16 at 14:00
  • @MarcoFerrari I have added a working example with explanation. – Max Feb 08 '16 at 15:56

2 Answers2

2

I would use ByteArrayInput stream or something that you can reset. That would involve reading the data into another type of input stream and then creating one.

InputStream has a markSupported() method that you could check on the original and the byte array one to find one that the mark will work with:

https://docs.oracle.com/javase/7/docs/api/java/io/InputStream.html#markSupported() https://docs.oracle.com/javase/7/docs/api/java/io/ByteArrayInputStream.html

mikeb
  • 10,578
  • 7
  • 62
  • 120
  • How would I be going on to do this? From what I understand is that I need to read the line with the `InputStream` and put the result in a `ByteArrayInputStream`. However, `markSupported()` has no effect and I cannot seem to read the `InputStream` for a second time. – Max Feb 08 '16 at 13:48
  • I seem to have it working now based upon your answer. However I did not use `ByteArrayInputStream`. I also used the regular `mark` and counted the amount of bytes I was in. And I've replaced `DataInputStream` to `BufferedInputStream`. – Max Feb 08 '16 at 15:57
1

The problem here is not re-reading the input. I don't see anything in the question that requires you to read the input twice. The problem is the BufferedInputStream, which will read everything that is available to be read, including the second message, if it has already arrived.

The solution is not to use a buffered stream until you have completed the handshake. Just issue a read on the socket input stream for exactly the length of the first message, do the handshake, and then proceed to construct and read the buffered stream.

user207421
  • 305,947
  • 44
  • 307
  • 483
  • The last piece of code is the solution I came up with myself (but as I said, it might not be the best way). The problem was that I could not read the `BufferedInputStream` for a second time after I sent some data over the `OutputStream`. However, this is fixed by using `mark()` and `reset()`. – Max Feb 16 '16 at 11:56