[Top][All Lists]

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: Reading data from a file descriptor

From: Amirouche Boubekki
Subject: Re: Reading data from a file descriptor
Date: Mon, 16 Nov 2015 11:54:33 +0100
User-agent: Roundcube Webmail/1.1.2

On 2015-11-13 21:41, Jan Synáček wrote:
On Fri, Nov 13, 2015 at 4:51 PM, Mark H Weaver <address@hidden> wrote:

Jan Synáček <address@hidden> writes:

> On Sun, Nov 8, 2015 at 12:49 AM, Andreas Rottmann <address@hidden>
> wrote:
>     Also note that if there's no requirement to actually implement
>     this in
>     C, there's `fdes->inport' and `fdes->outport' on the Scheme level,
>     so
>     something like the following would be analogous to the C example
>     code
>     posted:
>     (import (ice-9 binary-ports))
>     (define (process-fd fd)
>     (let ((port (fdes->inport fd)))
>     (display "read: ")
>     (display (get-bytevector-n port 100))
>     (display "\n")))
>     (process-fd (acquire-valid-fd))
> This is something very similar that I ended up with. Just instead of
> get-byte-vector, I used read-string!/partial.

I would advise against using 'read-string!/partial' or any of the
procedures in (ice-9 rw).  This is a vestigial module from Guile 1.8
when strings were arrays of bytes, which they no longer are. We should
probably mark them as deprecated.

For one thing, when we switch to using UTF-8 as the internal string
encoding, it will not be possible to keep 'read-string!/partial'
efficient.  It will necessarily have to do an encoding conversion.

In Guile 2+, I would advise using byte vectors when working with binary
data.  Portions of these can be converted to strings with a given
encoding if desired.  I might be able to give better advice if I knew
more about what you are doing here.


I have an open fd to a unix socket and I want to read data from it. I
know that the data is going to be only strings, but I don't know the
length in advance.

Do you know a delimiter? maybe it's the null char?

TCP is stream oriented, it's not structured at this layer into messages
or segments. You need some knowledge about the byte stream to be able to
split it into different meaningful piece for the upper layer.

In Python the socket.recv method returns bytestring but still you have to parse to bytestring to make sure the delimiter is not in the middle of the string. What I mean is that in theory you might socket.recv the end of an application level message
and the beginning of another using the same call.

Otherwise said, the only thing that could make sens for a (recv) procedure is to return the full content of the inbound network buffer for the given socket
as a bytevector but it will still require work to to make things work...

 The good thing about using read-string!/partial is,
that I don't have to specify how many bytes I want to read and it does
the right thing. If you point me to a better direction, I'll be
grateful. I came up with:

(for-each (lambda (fd)
            (let* ((buf (make-string 4096)))
              (read-string!/partial buf (fdes->inport fd))
              (format #t "fd[~a]: ~a" fd buf) (newline)))

Have a look at the implementation. IMO the solution is to build a loop with
(read-char) [1] looking for the *end char* to stop the loop.


reply via email to

[Prev in Thread] Current Thread [Next in Thread]