2

When I was using regular Sockets, I could call getInputStream() and use available() to see how many bytes were available. I switched to SSLSocket, but now available() always returns 0 for some reason. When I read instead, I can still get data. How can I tell if there is data available in an SSLSocket so that I can service it without blocking if there is no data?

Notes:

  • I cannot call read() on the InputStream or the thread will block. I would like non-blocking in my implementation.
  • available() returns 0 even though there is data for SSLSocket's InputStream.
xubia
  • 643
  • 9
  • 26
  • possible duplicate of [What does InputStream.available() do in Java?](http://stackoverflow.com/questions/3695372/what-does-inputstream-available-do-in-java) (check out the [second answer](http://stackoverflow.com/a/3695378/2398375)) – Vince Oct 12 '14 at 00:41
  • That is interesting. However, in my case, there is data available, therefore read() should not be blocking, and available should not return 0. – xubia Oct 12 '14 at 00:48
  • Check out the first comment to that answer as well - "*Note also that available() always returns zero for an SSL socket*". It would help to know why blocking is a problem in your case. Keep in mind, you are using blocking IO – Vince Oct 12 '14 at 00:53
  • Ah I see. Then does that mean there is no way to tell that there is data in an SSLSocket without reading from it? – xubia Oct 12 '14 at 00:57
  • Blocking is theoretically not a problem other than I need to refactor a lot of my code. I used Sockets instead of SSLSockets previously and used available(), so I was hoping the transition would be easier. – xubia Oct 12 '14 at 01:05
  • Have you tried wrapping your streams using `BufferedInputStream` and `BufferedOutputStream`? – Vince Oct 12 '14 at 01:25
  • Let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/62903/discussion-between-vince-emigh-and-aura). It's best to keep the comment section clean. I will post as an answer once the problem has been solved. – Vince Oct 12 '14 at 01:38
  • BufferedInputStream is exhibiting the same behavior. I might be content to wrap the regular Socket and do encryption at the application level if there is no good answer. – xubia Oct 14 '14 at 18:08
  • Please discuss this in the chat – Vince Oct 14 '14 at 20:40

3 Answers3

6

There is no way to do this. Your streams cannot tell you the length of the data without first decrypting it. available() will always return 0 for SSLSocket.

As mentioned in this chat, the reason you wanted to check for data is to prevent read() from blocking when called, so you can handle multiple connections on a single thread, instead of a Thread per Client system.

Instead, use a non-blocking alternative. java.nio currently doesn't have it's own SSL implementation of SocketChannel, but you can find one online (like here) or create your own.

With this system, you can register a Selector to every channel, and manage them all using the "selector thread". I wrote an example of how to use a selector here (scroll down to Using a Selector).

With non-blocking IO, you to handle multiple clients per thread, allowing you to scale up. This method of managing channels was brought up due to the C10k Problem

Community
  • 1
  • 1
Vince
  • 14,470
  • 7
  • 39
  • 84
4

I assume you fixed your problem, but for those like me, I found a much easier solution. If you perform a read, then the available() method fills up for what was decrypted. How to use and abuse this? Read a single byte with a very low SoTimeout on your socket, if you catch a SocketTimeoutException, then the connection is empty, if not, prepend that byte you read to your future interpretation of the message. Until in.available() == 0 again, just roll with it.

JavaProphet
  • 931
  • 14
  • 29
0

You can use available() with inputStream of underlying Socket. This works in my case.

Anupam
  • 1
  • 1
    Your answer could be improved with additional supporting information. Please [edit] to add further details, such as citations or documentation, so that others can confirm that your answer is correct. You can find more information on how to write good answers [in the help center](/help/how-to-answer). – Community Apr 20 '22 at 10:56