Re: non-blocking READ-SEQUENCE
ngo@cartan.de (=?iso-8859-1?q?Nils_G=F6sche?=) schrieb am 09.12.03 23:29:43:
>
> "Jochen Schmidt" <jsc@dataheaven.de> writes:
>
> > When developing efficient I/O over sockets one could think that
> > READ-SEQUENCE would be the right thing to transfer larger chunks at
> > a whole.
>
> Quite so.
>
> > A problem that arises is that READ-SEQUENCE blocks if the peer does
> > not send enought elements to fill the whole (bounded) sequence.
> >
> > What one would want is some kind of READ-SEQUENCE which blocks on
> > the first element and after that fills the sequence as long as data
> > is available on the socket. (semantically calling READ-CHAR-NO-HANG
> > until it returns NIL).
>
> It seems to me that you really want a message based network protocol
> and not a network stream. You could put a layer above your TCP stream
> by adding a header with a length. Then do a READ-SEQUENCE for the
> header, and another READ-SEQUENCE for the rest of the message.
If I would design a network protocol I may do it like this - yes.
Actually I'm implementing existing protocols which do not meet this criteria.
I've hacked together a function which, with enough internal voodoo, seems to do what I want:
(defun read-string-non-blocking
(string stream &key (start 0) (end (length string)))
;; Block on the first character
(let ((first-char (read-char stream)))
(setf (char string start) first-char)
(incf start))
;; Copy the rest of the input-buffer
;; into the string
(stream::with-stream-input-buffer
(buffer index limit) stream
(replace string buffer
:start1 start :end1 end
:start2 index :end2 limit)
(let ((n (min (- limit index)
(- end start))))
(incf start n)
(incf index n)))
;; non-blocking refill of input-buffer by setting
;; read-timeout to zero
(loop while (and (< start end)
(without-interrupts
(let ((timeout (stream:stream-read-timeout stream)))
(unwind-protect
(progn
(setf (stream:stream-read-timeout stream) 0)
(stream::stream-fill-buffer stream))
;; Restore former timeout value
(setf (stream:stream-read-timeout stream) timeout)))))
do
(stream::with-stream-input-buffer (buffer index limit) stream
(replace string buffer
:start1 start :end1 end
:start2 index :end2 limit)
(incf start (- limit index))
(setf index limit)))
start)
Perhaps this whole idea is just crap and the implementation bug-ridden and ugly - but I thought
it could bring in some new ideas to the topic.
ciao,
Jochen
______________________________________________________________________________
WEB.DE FreeMail wird 5 Jahre jung! Feiern Sie mit uns und
nutzen Sie die neuen Funktionen http://f.web.de/features/?mc=021130