Read Available for TCPStreams?

Monkey Targets Forums/Android/Read Available for TCPStreams?

Yeshu777(Posted 2015) [#1]
Hi,

What's the required method for checking there is data available on a TCP Stream before trying to read it?

Using Eof always returns 0 even if the stream is unreadable.

Any pointers?

Yeshu777


k.o.g.(Posted 2015) [#2]
I was trying to implement it.
It worked, but to hacky :/ ask mark lovely to implement it :D


ImmutableOctet(SKNG)(Posted 2015) [#3]
Getting past the synchronous setup of using a 'TcpStream' over a 'Socket', you basically just call 'ReadAll' without caring. But, unless you're looking to read a raw buffer, these will be called for you.

The point of a 'TcpStream' (Currently) is to read synchronously from a TCP connection, meaning it isn't able to perform these operations on other threads. Because of this, 'Eof' isn't always the most optimal way to check if the connection died. It will work, but not before other operations take place. If the connection was severed, the stream's 'Read' implementation would get a response from the system. It then sees this response, and if it was negative, it sets appropriate variables to ensure 'Eof' works, then returns.

If you're manually using 'Read' (Which could cause problems), this would cause the return-value to be 0 or less than 0. No questions asked, now 'Eof' works as expected, and you can't read from the stream. That being said, most operations performed with a 'Stream' use 'ReadAll'. 'ReadAll' is different, it's a "structured read", meaning it checks if data could be read, and continuously calls 'Read' until the number of bytes requested has been received. Commands like 'ReadInt' use this by default.

Alright, so the question is: "What happens when 'ReadAll' gets an invalid response from 'Read', because we disconnected?" - It throws an exception. This is how any stream-related code should handle errors like this. To be more specific, it calls its 'ReadError' method, which throws a 'StreamReadError' exception. After that's been caught, 'Eof' will work. The stream must still be closed once you are done. Closing the stream also closes the internal socket with it. This will not be done on a timeout/disconnection. You'll need to call 'Close' like every other 'Stream'.

"So, how do I check if there's something to read?" - The answer is, you don't. There isn't really a standard way of querying the system for this information. You either receive it, or you don't. There's two ways to do what you're asking, but they don't fit the envelope of a 'Stream'. The first is to receive, using the POSIX-standard 'select' command (Getting in to C territory here). This would be used to stall the current thread like it normally does, but the system would be able to use a timeout you set. The other way is to use another thread. This is possible using a 'Socket' directly, but is not possible with a 'TcpStream' (Currently). Basically, you would have a different thread wait, while you perform your usual work on the main thread.

Everything relating to input I just mentioned applies to output as well.


Yeshu777(Posted 2015) [#4]
Many thanks for the replies, had guessed as much.

Basically, I have a small app, connects to an FTP server usingTCP Socket, which is causing problems on V5 Android devices.

ie, reading the socket when there is nothing to read causes the app to crash / terminate (works fine on V4)

So, looks like I'll need to implement the same using Async Socket method, thanks for the confirmation.

Yeshu777