[racket] flush is not enough, a list is needed
Hi,
In a small Racket client/server over tcp, the client sends expressions that
the server evaluates and returns the result to the client, in a loop.
The tcp ports are flushed after each send, but it is still hanging, unless
I wrap the sent values in lists, which is a bit surprising.
So it looks like the buffer won't flush if it's not a list.
Is that a bug (maybe related to
http://bugs.racket-lang.org/query/?cmd=view&pr=12640 , but maybe not) or is
it me?
I can live with it though.
Client:
#lang racket/base
(require racket/tcp)
(printf "Trying to connect to server... ")
(define-values (in out) (tcp-connect "localhost" 54321))
(printf "Ok.\n")
(dynamic-wind
void
(λ()
(printf "rwind-client> ")(flush-output)
(define exit? #f)
(for ([e (in-port read)]
#:break (or exit? (equal? e '(exit)))
)
(printf "Sending: ~a\n" e)
; Wrap the output in a list, otherwise it may not be sent/flushed
(bug?)
(write (list e) out)
(flush-output out)
; receiving from server, unwrap
(define res (car (read in)))
(if (eof-object? res)
(set! exit? #t)
(begin
(printf "-> ~a\n" res)
(printf "rwind-client> ")(flush-output)))
))
(λ()
(printf "Closing connection.\n")
(close-input-port in)
(close-output-port out)))
Server:
#lang racket/base
(require racket/tcp)
(define-namespace-anchor a)
(define ns (namespace-anchor->namespace a))
(let () ; does this protect the listener from being visible to the
namespace?
(define listener (tcp-listen 54321))
(dynamic-wind
void
(λ()
;; Blocking
(let accept-loop ()
(printf "Waiting for client... ")(flush-output)
(define-values (in out) (tcp-accept listener))
(printf "Client is connected.\n")
(dynamic-wind
void
(λ()
(for ([e (in-port read in)]
#:break (equal? e '(exit))
)
(printf "Received ~a\n" e) ;(flush-output)
(define res
; if it fails, simply return the message
(with-handlers ([exn:fail? (λ(e)(exn-message e))])
; unwrap
(eval (car e) ns)))
(printf "Sending value: ~a ... " res) (flush-output)
; I need to wrap the output in a list, otherwise it may not be
sent/flushed! (bug?)
(write (list res) out) (flush-output out)
(printf "Ok.\n")
))
(λ()
(printf "Closing connection.\n")
(close-input-port in)
(close-output-port out)
;(accept-loop) ; uncomment this to not close the listener when
the client disconnects
))))
; out
(λ()(tcp-close listener))))
Also, unrelated to the problem above, I want to close everything correctly
when a problem occurs, but it seems that dynamic wind does not do that in
case of a break (e.g., if the exn handler is removed, an invalid operation
will raise an exception, but the ports will not be closed). I may be
misunderstanding what dynamic-wind does.
What would be the "right" way to do things here?
Thanks,
Laurent
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://lists.racket-lang.org/users/archive/attachments/20121102/d067d561/attachment.html>