Reading from Streams

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

Reading from Streams

Marco Qualizza

Hello all,


   I've been trying to figure out how to read from a Socket and not have it block.  So, I have my stream:


      ioStream := aSocketAccessor readAppendStream.

      ioStream lineEndCRLF.


   Now, I either want a non-blocking


      ioStream upTo: Character cr. "Yes, I'm reading one line of text at a time."


   or something like:


      "If there's data, return that data, otherwise return nil."

      ^ ioStream hasDataReady

         ifTrue: [ ioStream upTo: Character cr ]

         ifFalse: [ nil ].


   But, for the life of me, I can't figure it out.  #isEmpty doesn't do it (it always returns true), and #atEnd/#atEndOfData block.


   Any help or ideas would be appreciated.


      - M.


-- 

Marco Qualizza - (613) 895-2078

"Elegance is not optional." (Richard O'Keefe)

Reply | Threaded
Open this post in threaded view
|

Re: Reading from Streams

kobetic
This is actually kinda tricky especially with the Streams involved. You
can check a SocketAccessor if it has any pending unread data using
#bytesForRead. So

        aSocketAccessor bytesForRead

should tell you if there is data in the OS socket buffers ready to be
read in (I think).

However socket streams use internal buffering, so you'd really also need
to check if there's anything left in the stream buffer that you didn't
pull out of the stream yet. I'm not even sure how to do that
(#basicAtEnd maybe, but that's private anyway).

Note that even if you were able to do that. You still can't simply issue
an 'upTo: CR' because if there's no CR in that pending data, you'll end
up blocked at the end of it anyway.

Personally, I always found that when I needed this sort of control, the
stream was just getting in the way. It's usually easier to just drop to
the socket level and use the #readInto:/writeFrom: and
#readWaitWithTimeout: API. You can find more on that in the
documentation on sockets (used to be in NetClientDevGuide.pdf before,
now in 7.4 it's in BasicLibraries.pdf, I believe).

Once you get the bytes into the image you can start streaming over it
using internal streams.

HTH,

Martin

Marco Qualizza wrote:

> Hello all,
>
>    I've been trying to figure out how to read from a Socket and not have it block.  So, I have my stream:
>
>       ioStream := aSocketAccessor readAppendStream.
>       ioStream lineEndCRLF.
>
>    Now, I either want a non-blocking
>
>       ioStream upTo: Character cr. "Yes, I'm reading one line of text at a time."
>
>    or something like:
>
>       "If there's data, return that data, otherwise return nil."
>       ^ ioStream hasDataReady
>          ifTrue: [ ioStream upTo: Character cr ]
>          ifFalse: [ nil ].
>
>    But, for the life of me, I can't figure it out.  #isEmpty doesn't do it (it always returns true), and #atEnd/#atEndOfData block.
>
>    Any help or ideas would be appreciated.
>
>       - M.
>

Reply | Threaded
Open this post in threaded view
|

Re[2]: Reading from Streams

Marco Qualizza

Hello Martin,


   I'm writing what is effectively a telnet server, so there are no issues with partial lines (ie/ having data and not having it crlf-terminated).  I've just tried #bytesForRead, and it seems to do the trick.  You've raised a good point regarding buffering, I'll have to look into it.


   Thanks,

      - M.


Wednesday, January 18, 2006, 10:02:37 PM, you wrote:


> This is actually kinda tricky especially with the Streams involved. You 

> can check a SocketAccessor if it has any pending unread data using 

> #bytesForRead. So


>         aSocketAccessor bytesForRead


> should tell you if there is data in the OS socket buffers ready to be 

> read in (I think).


> However socket streams use internal buffering, so you'd really also need 

> to check if there's anything left in the stream buffer that you didn't 

> pull out of the stream yet. I'm not even sure how to do that 

> (#basicAtEnd maybe, but that's private anyway).


> Note that even if you were able to do that. You still can't simply issue 

> an 'upTo: CR' because if there's no CR in that pending data, you'll end 

> up blocked at the end of it anyway.


> Personally, I always found that when I needed this sort of control, the 

> stream was just getting in the way. It's usually easier to just drop to 

> the socket level and use the #readInto:/writeFrom: and 

> #readWaitWithTimeout: API. You can find more on that in the 

> documentation on sockets (used to be in NetClientDevGuide.pdf before, 

> now in 7.4 it's in BasicLibraries.pdf, I believe).


> Once you get the bytes into the image you can start streaming over it 

> using internal streams.


> HTH,


> Martin


> Marco Qualizza wrote:


>> Hello all,


>>    I've been trying to figure out how to read from a Socket and not have it block.  So, I have my stream:


>>       ioStream := aSocketAccessor readAppendStream.

>>       ioStream lineEndCRLF.


>>    Now, I either want a non-blocking


>>       ioStream upTo: Character cr. "Yes, I'm reading one line of text at a time."


>>    or something like:


>>       "If there's data, return that data, otherwise return nil."

>>       ^ ioStream hasDataReady

>>          ifTrue: [ ioStream upTo: Character cr ]

>>          ifFalse: [ nil ].


>>    But, for the life of me, I can't figure it out.  #isEmpty doesn't do it (it always returns true), and #atEnd/#atEndOfData block.


>>    Any help or ideas would be appreciated.


>>       - M.





-- 

Marco Qualizza - (613) 895-2078

"Elegance is not optional." (Richard O'Keefe)