42 lines
1.5 KiB
Scheme
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)))))
|