[Openmcl-devel] Read all available input from socket stream?

Joshua Kordani jkordani at lsa2.com
Wed Jul 24 14:25:12 PDT 2013

Your code works for me.

I realize that I was mixing my metaphors up.  I am receiving a message 
that I was assuming would fit inside one packet, and what I was wanting 
to write was code that assumed this, blocked until input, and once input 
came in, read the entirety of it, no matter how large, into something I 
could use.  The CLHS example for read-sequence successfully reads into 
an array less data than the size of the array allocated.  this lead me 
to suspect that I could do the same thing with a ccl socket stream, but 
it seems that read-sequence won't come back until the array is 
completely filled. So if I want to issue a message and expect a variable 
length response, I can't make the assumption that the entire response 
will arrive inside one packet (even though I'm pretty sure that this is 
the case, as I'm in control of all of the hardware that sits between me 
and the device in question, and I will never receive a response larger 
than say 100 bytes.  I was making that assumption, and also the 
assumption that read-sequence would encounter eof when there was no more 
data to be read.

It seems that the correct approach is to walk through the input a byte 
at a time and look for the end of message byte specified by the protocol 
I'm using, and if I stop reading before I get to the end of input I know 
I need to take what comes next and append it to what I've collected so 
far (or leave the buffer alone until I can read a full message out)  
This last activity I've done before in other languages,  I should take 
some time to figure out how this same kind of work would be done in CL.

For posterity, the code that does what I want is here: 

On 7/24/13 6:31 AM, Gary Byers wrote:
> Here's a very simple test case that tries to do something similar to
> what your code is apparently trying to do.
> ;---
> (defun server ()
>   (let* ((lsock (make-socket :connect :passive :local-host "localhost" 
> :local-port 40000 :reuse-address t))
>          (data (make-array 10 :element-type '(unsigned-byte 8))))
>     (dotimes (i 10) (setf (aref data i) i))
>     (let* ((stream (accept-connection lsock :wait t)))
>       (write-sequence data stream)
>       (when t
>         (sleep 5)
>         (write-sequence data stream))
>       (close stream)
>       (close lsock))))
> (defun test ()
>   (process-run-function "server" #'server)
>   (let* ((stream (make-socket :remote-host "localhost" :remote-port 
> 40000))
>          (data (make-array 19 :element-type '(unsigned-byte 8)))
>          (n (read-sequence data stream)))
>     (close stream)
>     (format t "~& requested 19 octets, got ~d" n)))
> ;---
> Calling (TEST) shoud pause for ~5 seconds, then report that it requested
> and go 19 octets.  Does this fail for you ?  If not, how does the code
> that you're dealing with differ ?
> If you change the WHEN T in #'SERVER to WHEN NIL (and wait a few minutes,
> since I'm likely not using :reuse-address correctly), the server will 
> close
> its side of the connection after writing 10 octets; READ-SEQUENCE will 
> see
> that the stream is at EOF after those 10 octets are read.  This (EOF) 
> is the
> only situation in which READ-SEQUENCE should return prematurely, and 
> it's the
> only situation I'm aware of in which it does so in CCL.
> On Tue, 23 Jul 2013, Joshua Kordani wrote:
>> Greetings all.
>> I am attempting to read all currently available data from a stream.? 
>> I am
>> not expecting much data, so I suspect I need to call finish-output.? 
>> (read)
>> seems to return immediately, before it seems that data is available.? I
>> guess in hindsight I don't know how the implementation is supposed to 
>> know
>> when input has stopped coming in on what is conceptually a stream 
>> with no
>> eof representing any termination of input.
>> I guess what I'm saying is, given a socket stream, is there a way to 
>> read,
>> blocking until there is input to be read and until there is no more 
>> data to
>> be read, this kind of stream?
>> http://paste.lisp.org/+2YLT
>> this is a paste of the funciton I'm trying to get working.? I want to 
>> write
>> something to the stream, and I expect something back, which I want to 
>> either
>> return from this function or simply emit to *terminal-io*
>> Josh

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <https://lists.clozure.com/pipermail/openmcl-devel/attachments/20130724/75df66c9/attachment.htm>

More information about the Openmcl-devel mailing list