readLine on socket works while available() and ready() disagree

K

kevin.osborne

I'm reading some bytes over a socket off a non-http server.

After writing a message to the socket, I grab the return stream with:

InputStream stream = _ssl_socket.getInputStream();
From this object, I get the following advisements:

stream.available() [result: 0]
(new InputStreamReader(stream)).ready() [result: false]

And yet:

(new BufferedReader(new InputStreamReader(stream))).readLine()

Returns the expected response from the server.

However, readLine clobbers cr/lf chars, which are integral parts of my
incoming datastream, and define its structure. There are separate 0x0a
& 0x0d carhs scattered throughout the stream, and no quibbling; I need
them.

My peeve here is that because stream.available() returns 0, I cannot
predeclare a char array of a commensurate size with the inclong data,
and must instead allocate unncessary memory to an oversize array. i.e
because:

char[] char_buff = new char[stream.available()];
read_result = stream_reader.read(char_buff, 0, stream.available());

doesn't work, I have to do:

char[] char_buff = new char[MAX_MESSAGE_SIZE];
read_result = stream_reader.read(char_buff, 0, MAX_MESSAGE_SIZE);

where MAX_MESSAGE_SIZE is dictated by the foriegn server, and is
enormous. and no I cannot change the foreign server behaviour in any
way shape or form.

So my options are:

- use readLine, and butcher my input beyond usable form
- waste memory on hugely oversized char arrays for mostly tiny
messages
- use int read() and crawl through the stream char by char

i.e. cost myself correctness, memory and cpu/network performance
respectively.

Ideally I'd like a working available() call to be able to sensibly
declare my char array, and then do the read. If it helps the conundrum
of ready=false/available=0/readLine=lots'o'data, this is all happenning
via an SSLSocket connection.

TIA
Kevin
 
A

Andrew Thompson

...I have to do:

char[] char_buff = new char[MAX_MESSAGE_SIZE];
read_result = stream_reader.read(char_buff, 0, MAX_MESSAGE_SIZE);

where MAX_MESSAGE_SIZE is dictated by the foriegn server, ..

No it is not. Your array can be '64 bytes'* and the rest of
the data is there, waiting for you on the next loop.

* A ludicrously small amount, not actually tested, something
like '4096' is much more common.
 
K

kevin.osborne

my undisclosed option 4; the tradeoff in this case is elegance, in
comparison with new char[available()], but it is the interim winner.

Any ideas as to why available() returns zero?
 
G

Gordon Beaton

Any ideas as to why available() returns zero?

Because at the moment you call it there is no data waiting to be read.
available() doesn't tell you how much data the peer is in the process
of (or has the intention of) sending. It tells you how much has
actually arrived at your end of the connection, which may be anything
between zero and the total length of the expected data.

For the record, available() will cause you other grief as well, such
as trying to determing when you've reached EOF on the stream.

Blocking calls like read() or readLine() wait until data arrives
before returning it to you.

One of your options mentioned reading character at a time. You could
use BufferedReader.read() and put together a line of data yourself in
much the same way as readLine() does but without stripping the EOL
characters. However I don't see what's wrong with adding back the EOL
chars that readLine() removed.

Or as another poster suggested, reading "bufsize" (e.g. 4096)
characters, checking, then repeating until you get to EOL. Let the
buffer grow a little if it's too short for the current line. After you
reach your longest line it won't have to grow anymore, it will be long
enough without being excessively long.

If you have control of the protocol itself, consider prefixing each
message with its length. It's easier than looking for message
separators like newlines.

Regardless of which option you choose, realize that looping to get a
complete response is always necessary (whether you do it or a library
function does it for you), even if you know the length in advance.

/gordon
 
K

kevin.osborne

magic - great answers guys. many thanks for your help!

for the record, the input has 0x0d, 0x0a, and 0x0d0a throughout, each
one has a diffrent meaning. readLine() strips any of them on sight,
after which I've no way of reconstituting a meaningful message.

As it is, available() gave me false hope; apologies for reaching and
thanks again for taking the time to help me out.

health/regards
Kevin
 
R

Roedy Green

for the record, the input has 0x0d, 0x0a, and 0x0d0a throughout, each
one has a diffrent meaning. readLine() strips any of them on sight,
after which I've no way of reconstituting a meaningful message.

an array of strings for most purposes is meaningful. If the
particular separators are significant, don't use readLine. See
http://mindprod.com/applets/fileio.html
for how to read great hunks at a time.
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
473,755
Messages
2,569,536
Members
45,013
Latest member
KatriceSwa

Latest Threads

Top