;; 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