Socket streams

Previous Topic Next Topic
 
classic Classic list List threaded Threaded
2 messages Options
Reply | Threaded
Open this post in threaded view
|

Socket streams

Bill Schwab-2
Blair,

SocketReadStream does not always do what one would expect.  #contents,
#nextLine, #upToEnd will answer an empty collection even when the socket has
data available.  The #nextLine below seems to work, but I suspect that it
would be happier written in terms of #contentsSpecies or something.  More
generally, is there some way to use #hasInput to get the stream to read from
the socket before returning an empty collection?

Have a good one,

Bill



!SocketReadStream methodsFor!

nextLine
 "Answer a Collection consisting of the receiver contents up to (but not
including) the
 next line delimiter. If there are no further line delimiters in the
receiver, then the
 rest of the receiver's contents are answered. If the receiver is at its
end, then an empty
 collection is answered.
 N.B. This method works for Unix and Windows line delimiters (that is CR/LF
and LF
 sequences respectively), but not if the line delimiter consists solely of a
CR."

 | result eol |
 eol := String lineDelimiter asByteArray.
 result := self upTo: eol last.
 ^(result notEmpty and: [result last = eol first])
  ifTrue: [result allButLast]
  ifFalse: [result]! !
!SocketReadStream categoriesFor: #nextLine!accessing!public! !


--
Wilhelm K. Schwab, Ph.D.
[hidden email]


Reply | Threaded
Open this post in threaded view
|

Re: Socket streams

Blair McGlashan
Bill

You wrote in message news:bn3l85$sjlbr$[hidden email]...
>
> SocketReadStream does not always do what one would expect.

I can only agree with that. With the benefit of hindsight we can see that it
was probably a design error to subclass SocketReadStream from
PositionableStream. This allows it to inherit some useful buffering
implementation behaviour, but it has also picked up quite a lot of
inappropriate behaviour, as SocketReadStreams are not really positionable at
all.

>...#contents,
> #nextLine, #upToEnd will answer an empty collection even when the socket
has
> data available.

Hmmm, I don't think #contents should be available at all. SocketReadStreams
are not really ANSI <sequencedStream>s. #contents should answer a collection
"that contains the receiver's past and future sequence values". This would
require that the stream retain all previous data and then all subsequent
data up until the associated socket is closed. I don't think that buffering
all the "past sequence" values makes sense for a generic socket stream - one
should write a <sequencedStream> that can be layered onto a simple
<gettableStream> for that purpose.

#upToEnd should answer all the "future sequence values", i.e. up to the end
of stream when the socket is closed. This probably isn't that useful on
Sockets either. I think the Stream implementation of #upToEnd should be
copied down to SocketReadStream because the implementation in
PositionableStream is inappropriate.

>...The #nextLine below seems to work, but I suspect that it
> would be happier written in terms of #contentsSpecies or something.

Yes, although it is questionable whether #nextLine is useful on binary
streams in general, I suppose it is up to the application programmer not to
call it against a true binary data stream. On the other hand I would prefer
it if SocketReadStream supported mutually exclusive binary or text modes, as
in FileStream.

>...More
> generally, is there some way to use #hasInput to get the stream to read
from
> the socket before returning an empty collection?

Well as I've said I don't think #contents should be implemented at all.
Other reading methods (e.g. #next[:], #upToEnd, #upTo:, etc) should block
until the input is available, or the socket is closed. #nextAvailable:
should be the only non-blocking read.

Unfortunately I don't think it is appropriate to change any of this in a
patch level. Our policy now is to try and avoid making "breaking" changes in
patches. It seems likely that changing these behaviours, incorrect as they
might be, will break existing code.

Regards

Blair