[racket] Issue reading bytes from TCP port

129 views
Skip to first unread message

Gilbert Martinez

unread,
Sep 3, 2014, 12:04:05 PM9/3/14
to us...@racket-lang.org
I'm having issues reading the response from a TCP server.  Specifically, any attempt to read the input port does not terminate.  I've used port->bytes, read-byte, and read-line. In all cases the effect is the same.

I thought that if there were no bytes available on an input port that the read attempt would just return <eof>.  Is this some kind of exclusivity issue?  Can I not read from the port until the connection with the server is closed or something?

My traffic monitor shows that the server is receiving the request and responding (here is the exchange):

Time Src. & Dst. Type Function Code Data
908.875    10.10.10.10:49967<- TCP Req. 0x04 [0x000 - 0x027]     00 01 00 00 00 06 0B 04    00 3B 00 03
908.90510.10.10.10:49967-> TCP Resp. 0x04 [0x000 - 0x027]     00 01 00 00 00 09 0B 04    06 00 00 00 00 00 00

Here is the code I am using to query:

#lang racket


(define (hex-bytes->bytes hex-bytes-list)
  (define (hex-byte->dec-byte hex-byte)
    (string->number (string-append "#x" ((if (symbol? hex-byte)
                                             symbol->string
                                             number->string)
                                         hex-byte))))
  (apply bytes (for/list ((hex-byte (in-list hex-bytes-list)))
                 (hex-byte->dec-byte hex-byte))))

(define-values (c-in c-out) (tcp-connect "10.10.10.11" 502))

(write-bytes (hex-bytes->bytes '(00 01 00 00 00 06 0B 04 00 3B 00 03)) c-out)
(flush-output c-out)


I run the code above and execute the following in the interactions pane:

Welcome to DrRacket, version 6.1.0.5--2014-08-25(32ae3f8/a) [3m].
Language: racket [custom].
12
>(for ((byte (in-bytes (port->bytes c-in))))
  (printf "~x " byte))


The entry above above hangs on port->bytes.

Matthias Felleisen

unread,
Sep 3, 2014, 12:21:19 PM9/3/14
to Gilbert Martinez, us...@racket-lang.org

Have you tried closing the ports? -- Matthias



____________________
 Racket Users list:
 http://lists.racket-lang.org/users

Neil Van Dyke

unread,
Sep 3, 2014, 12:25:27 PM9/3/14
to Gilbert Martinez, us...@racket-lang.org

Gilbert Martinez wrote at 09/03/2014 12:01 PM:

I run the code above and execute the following in the interactions pane:

Welcome to DrRacket, version 6.1.0.5--2014-08-25(32ae3f8/a) [3m].
Language: racket [custom].
12
>(for ((byte (in-bytes (port->bytes c-in))))
  (printf "~x " byte))


The entry above above hangs on port->bytes.

Unless "in-bytes" is doing more magic than I feared, I believe that here "port->bytes" is a procedure that reads all the input to the end-of-file (which won't happen until the TCP connection is closed), before "in-bytes" or "for" or anyone else sees anything from the port.

"port->bytes" is a convenience, mainly for reading files.  You instead probably want to read one byte at a time from the port, or (a little harder) to do block reads of available bytes from the port.

BTW, I think this is another example of how "for" and friends are confusing to people.  I still think that people are better off first learning how to do things using named-"let" and mutually-recursive procedures *before* being introduced to "for".  (My biggest objection is that people introduced to "for" first then end up shoehorning control-flow into "for" even when it doesn't fit.  But I'm saving this new kind of anecdote, about syntactic sugar obscuring evaluation model, as additional evidence of "for"'s crimes against humanity.)

Neil V.


David Vanderson

unread,
Sep 3, 2014, 5:52:10 PM9/3/14
to us...@racket-lang.org
On 09/03/2014 12:01 PM, Gilbert Martinez wrote:
I'm having issues reading the response from a TCP server.  Specifically, any attempt to read the input port does not terminate.  I've used port->bytes, read-byte, and read-line. In all cases the effect is the same.

I thought that if there were no bytes available on an input port that the read attempt would just return <eof>.  Is this some kind of exclusivity issue?  Can I not read from the port until the connection with the server is closed or something?
This is not true.  Most functions like 'read-byte' block until there are bytes available to read.  You don't get <eof> until the port (connection) is closed.  If you want a non-blocking call, look at 'read-bytes-avail!*'.

#lang racket

(define-values (in out) (make-pipe))

(thread
 (lambda ()
   (for ((i 5))
     (write-byte i out)
     (sleep 1))
   (close-output-port out)))

(for ((b in))
  (printf "~x " b))

'for' is pretty smart in my experience.  I believe in this case it's using a sequence from 'in-port'.  But in any case, you should see numbers print out before the port is closed.

Does this help?

Thanks,
Dave
Reply all
Reply to author
Forward
0 new messages