Hi,<br><br>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.<br>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.<br>
So it looks like the buffer won't flush if it's not a list.<br>Is that a bug (maybe related to <a href="http://bugs.racket-lang.org/query/?cmd=view&pr=12640">http://bugs.racket-lang.org/query/?cmd=view&pr=12640</a> , but maybe not) or is it me? <br>
I can live with it though.<br><br>Client:<br>#lang racket/base<br><br>(require racket/tcp)<br><br>(printf "Trying to connect to server... ")<br>(define-values (in out) (tcp-connect "localhost" 54321))<br>
(printf "Ok.\n")<br><br>(dynamic-wind<br> void<br> (ë()<br> (printf "rwind-client> ")(flush-output)<br> (define exit? #f)<br> (for ([e (in-port read)]<br> #:break (or exit? (equal? e '(exit)))<br>
)<br> (printf "Sending: ~a\n" e)<br> ; Wrap the output in a list, otherwise it may not be sent/flushed (bug?)<br> (write (list e) out)<br> (flush-output out)<br><br> ; receiving from server, unwrap<br>
(define res (car (read in)))<br> (if (eof-object? res)<br> (set! exit? #t)<br> (begin<br> (printf "-> ~a\n" res)<br> <br> (printf "rwind-client> ")(flush-output)))<br>
))<br> (ë()<br> (printf "Closing connection.\n")<br> (close-input-port in)<br> (close-output-port out)))<br><br><br>Server:<br>#lang racket/base<br><br>(require racket/tcp)<br><br>(define-namespace-anchor a)<br>
(define ns (namespace-anchor->namespace a))<br><br>(let () ; does this protect the listener from being visible to the namespace?<br> (define listener (tcp-listen 54321))<br> <br> (dynamic-wind<br> void<br> (ë()<br>
;; Blocking<br> (let accept-loop ()<br> (printf "Waiting for client... ")(flush-output)<br> (define-values (in out) (tcp-accept listener))<br> (printf "Client is connected.\n")<br>
<br> (dynamic-wind<br> void<br> (ë()<br> (for ([e (in-port read in)]<br> #:break (equal? e '(exit))<br> )<br> (printf "Received ~a\n" e) ;(flush-output)<br>
(define res <br> ; if it fails, simply return the message<br> (with-handlers ([exn:fail? (ë(e)(exn-message e))])<br> ; unwrap<br> (eval (car e) ns)))<br>
(printf "Sending value: ~a ... " res) (flush-output)<br> ; I need to wrap the output in a list, otherwise it may not be sent/flushed! (bug?)<br> (write (list res) out) (flush-output out)<br>
(printf "Ok.\n")<br> ))<br> (ë()<br> (printf "Closing connection.\n")<br> (close-input-port in)<br> (close-output-port out)<br> ;(accept-loop) ; uncomment this to not close the listener when the client disconnects<br>
))))<br> ; out<br> (ë()(tcp-close listener))))<br><br><br><br>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.<br>
What would be the "right" way to do things here?<br><br><br>Thanks,<br>Laurent<br>