Hi all, 

i wrote a simple echo server/client. To catch SIGCHLD signal, i install
a signal handler before first `connect'. The problem is that when the
client exits, the handler seems not called. Instead, upon a new client
connected to the server, the handler will be called(due to last
client's exit). 

To summarize, 

,----[ first client ]
| $ guile -e main server.scm
| server started on localhost:10000
| New client(#(2 2130706433 54570)) incomming
| 
| $ guile -e main client.scm
| connected to server
| hi
| hi
| 
| $ 
`----

,----[ second client ]
| $ guile -e main server.scm
| server started on localhost:10000
| New client(#(2 2130706433 47200)) incomming
| child 16648 terminated
| New client(#(2 2130706433 47201)) incomming
| 
| $ guile -e main client.scm
| connected to server
| hey
| hey
| 
| $ 
`----

Can the signal handler be called as soon as the client exits?

Attchments are testing codes.
 
-- 
William

Work continues in this area.
                -- DEC's SPR-Answering-Automaton
;; echo client

(use-modules (ice-9 optargs))
(use-modules (ice-9 getopt-long))
(use-modules (ice-9 rdelim))

(define (hostname->ip hostname)
  "Convert HOSTNAME to its IP.
e.g.,
    (hostname->ip \"www.google.com\")  => \"64.233.189.104\""
  (inet-ntop AF_INET (car (hostent:addr-list (gethost hostname)))))


(define (main args)
  (let* ((option-spec '((help (single-char #\h) (value #f))
                        (host (single-char #\H) (value #t))
                        (port (single-char #\p) (value #t))))
         (options (getopt-long args option-spec)))
    (if (option-ref options 'help #f)
        (usage)
        (client (option-ref options 'host "localhost")
                (option-ref options 'port "10000")))))

(define (usage)
  (display "\
Usage: client.scm [OPTIONS]
  -h, --help              show this help
  -H, --host=LOCALHOST    remote address
  -p, --port=10000        remote port
")
  (exit 1))

(define (client host port)
  (let ((s (socket PF_INET SOCK_STREAM 0))
        (host-ip (hostname->ip host))
        (port-value (string->number port)))
    (connect s AF_INET (inet-pton AF_INET host-ip) port-value)
    (display "connected to server\n")
    (echo-loop s)))

(define (echo-loop server-port)
  (let ((line (read-line (current-input-port) 'concat)))
    (while (not (eof-object? line))
           (display line server-port)
           (display (read-line server-port 'concat))
           (set! line (read-line (current-input-port) 'concat)))
    (close server-port)))

;;; client.scm ends here
;; echo server

(use-modules (ice-9 optargs))
(use-modules (ice-9 format))
(use-modules (ice-9 getopt-long))
(use-modules (ice-9 rdelim))

(define (hostname->ip hostname)
  "Convert HOSTNAME to its IP.
e.g.,
    (hostname->ip \"www.google.com\")  => \"64.233.189.104\""
  (inet-ntop AF_INET (car (hostent:addr-list (gethost hostname)))))


(define (main args)
  (let* ((option-spec '((help (single-char #\h) (value #f))
                        (host (single-char #\H) (value #t))
                        (port (single-char #\p) (value #t))))
         (options (getopt-long args option-spec)))
    (if (option-ref options 'help #f)
        (usage)
        (server (option-ref options 'host "localhost")
                (option-ref options 'port "10000")))))

(define (usage)
  (display "\
Usage: server.scm [OPTIONS]
  -h, --help              show this help
  -H, --host=LOCALHOST    listening address
  -p, --port=10000        listening port
")
  (exit 1))

(define (server host port)
  (let* ((s (socket PF_INET SOCK_STREAM 0))
         (host-ip (hostname->ip host))
         (port-value (string->number port)))
    (setsockopt s SOL_SOCKET SO_REUSEADDR 1)
    (bind s AF_INET (inet-pton AF_INET host-ip) port-value)
    (listen s 5)
    (format #t "server started on ~a:~a\n" host port)
    (sigaction SIGCHLD
               (lambda (sig)
;;                  (let ((pid (car (waitpid -1 WNOHANG))))
;;                    (while (> pid 0)
;;                           (format #t "child ~d terminated\n" pid)
;;                           (set! pid (car (waitpid -1 WNOHANG)))))))
                 (format #t
                         "child ~d terminated\n"
                         (car (waitpid -1 WNOHANG)))))
    (while #t
           (let* ((client (accept s))
                  (client-port (car client)))
             (format #t "New client(~S) incomming\n" (cdr client))
             (and (zero? (primitive-fork)) ; child
                  (begin (close-port s)
                         (echo-loop client-port)
                         (primitive-exit)))
             (close-port client-port)))))

(define (echo-loop port)
  "Read from PORT and send back."
  (let ((line (read-line port 'concat)))
    (while (not (eof-object? line))
           (display line port)
           (set! line (read-line port 'concat)))
    (close-port port)))

;;; server.scm ends here
_______________________________________________
Guile-user mailing list
Guile-user@gnu.org
http://lists.gnu.org/mailman/listinfo/guile-user

Reply via email to