RosettaCodeData/Task/Echo-server/Scheme/echo-server.ss

42 lines
1.5 KiB
Scheme

; Needed in Guile for read-line
(use-modules (ice-9 rdelim))
; Variable used to hold child PID returned from forking
(define child #f)
; Start listening on port 12321 for connections from any address
(let ((s (socket PF_INET SOCK_STREAM 0)))
(setsockopt s SOL_SOCKET SO_REUSEADDR 1)
(bind s AF_INET INADDR_ANY 12321)
(listen s 5) ; Queue size of 5
(simple-format #t "Listening for clients in pid: ~S" (getpid))
(newline)
; Wait for connections forever
(while #t
(let* ((client-connection (accept s))
(client-details (cdr client-connection))
(client (car client-connection)))
; Once something connects fork
(set! child (primitive-fork))
(if (zero? child)
(begin
; Then have child fork to avoid zombie children (grandchildren aren't our responsibility)
(set! child (primitive-fork))
(if (zero? child)
(begin
; Display some connection details
(simple-format #t "Got new client connection: ~S" client-details)
(newline)
(simple-format #t "Client address: ~S"
(gethostbyaddr (sockaddr:addr client-details)))
(newline)
; Wait for input from client and then echo the input back forever (or until client quits)
(do ((line (read-line client)(read-line client))) ((zero? 1))
(display line client)(newline client))))
; Child exits after spawning grandchild.
(primitive-exit))
; Parent waits for child to finish spawning grandchild
(waitpid child)))))