Can someone help me with a client-server application I have written?
I have attached some code below with a description of the problem in
the opening comments. Maybe you can tell what I am doing wrong just
from looking at those comments.
;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;; $Id: test-server.scm,v 1.6 2003/01/03 15:54:08 kademan Exp $
;;;
;;; This program is a simplified version of a client-server system I
;;; have written. It demonstrates that if the client process dies
;;; between the time the server recognizes the connection and the time
;;; it tries to write the information out to the associated port the
;;; server dies as well, with a "Broken pipe" error. The error
;;; appears to be untrappable. I want to trap the error---or prevent
;;; it in the first place.
;;;
;;; I have tried this with Scsh 0.6.3 under Solaris 2.6 and Scsh 0.6.2
;;; under Linux 2.4.18-3smp.
;;;
;;; I have found that the server doesn't die if I remove the
;;; `set-port-buffering' invocation, but in that case it doesn't trap
;;; an error either. In my real application the server dies whether I
;;; turn off buffering or not.
;;;
;;; How to run the server and client:
;;; scsh -o threads -l test-server.scm -e server -s test-server.scm &
;;; scsh -o threads -l test-server.scm -e client -s test-server.scm
;;;
;;; As soon as the server prints the, "Got a connection" message kill
;;; the client by hitting CTRL-C. I get the following after a few
;;; seconds:
;;;
;;; Error: exception
;;; os-error
;;; (channel-maybe-write '#{Byte-vector 39} 0 1 '#{Output-channel 6}
"Broken pipe")
(define port-number 2001)
(define (sec->msec sec) (* 1000 sec))
(define (hostname) (car (run/strings (hostname))))
(define (test-server seconds)
(bind-listen-accept-loop
protocol-family/internet
(lambda (sock socket-address)
(with-errno-handler
((errno packet)
(else (format #t "errno: ~D~%~A~%" errno (car packet))))
(set-port-buffering (socket:outport sock) bufpol/none)
(format #t "Got a connection, will wait ~D seconds~%" seconds)
(sleep (sec->msec seconds))
(write "hi" (socket:outport sock))
(close-socket sock)))
port-number))
(define (get-message-from server)
(let* ((sock (socket-connect protocol-family/internet
socket-type/stream
server
port-number))
(msg (read (socket:inport sock))))
(close-socket sock)
msg))
(define (test-client server)
(format #t "I just got ~A from server ~A~%"
(get-message-from server) server)
(sleep (sec->msec 2))
(test-client server))
(define (server args) (test-server 5))
(define (client args) (test-client (hostname)))
|