Mark ENOLINK and EMULTIHOP as optional
[iolib.git] / examples / ex3-server.lisp
blob4cdb755c9a0a2aa255d5ed8023eaf7013142ff35
1 (in-package :iolib.examples)
3 ;;;; This file was originally written by Peter Keller (psilord@cs.wisc.edu)
4 ;;;; and this code is released under the same license as IOLib.
6 ;;;; This is a more common-lisp-like style of ex2-server, and to be
7 ;;;; used for the rest of the examples as appropriate. We introduce
8 ;;;; with-open-socket, which does a lot of cleanup on the created
9 ;;;; socket and ensures it is closed. This is usually the recommended
10 ;;;; idiom for simple clients.
12 ;;;; Also in this example we start to handle some of the more common
13 ;;;; conditions which can be signaled by IOLib.
15 ;; ex-0b
16 (defun run-ex3-server-helper (port)
17 (with-open-socket
18 (server :connect :passive
19 :address-family :internet
20 :type :stream
21 :ipv6 nil
22 :external-format '(:utf-8 :eol-style :crlf))
24 (format t "Created socket: ~A[fd=~A]~%" server (socket-os-fd server))
26 ;; Bind the socket to all interfaces with specified port.
27 (bind-address server +ipv4-unspecified+ :port port :reuse-addr t)
28 (format t "Bound socket: ~A~%" server)
30 ;; start listening on the server socket
31 (listen-on server :backlog 5)
32 (format t "Listening on socket bound to: ~A:~A~%"
33 (local-host server)
34 (local-port server))
35 ;; ex-0e
37 ;; ex-1b
38 ;; keep accepting connections forever.
39 (loop
40 (format t "Waiting to accept a connection...~%")
42 ;; Here we see with-accept-connection which simplifies closing
43 ;; the client socket when are done with it.
44 (with-accept-connection (client server :wait t)
45 ;; When we get a new connection, show who it
46 ;; is from.
47 (multiple-value-bind (who rport)
48 (remote-name client)
49 (format t "Got a connnection from ~A:~A!~%" who rport))
51 ;; Since we're using an internet TCP stream, we can use format
52 ;; with it. However, we should be sure to finish-output in
53 ;; order that all the data is sent.
54 (multiple-value-bind (s m h d mon y)
55 (get-decoded-time)
56 (format t "Sending the time...")
58 ;; Catch the condition of the client closing the connection.
59 ;; Since we exist inside a with-accept-connection, the
60 ;; socket will be automatically closed.
61 (handler-case
62 (progn
63 (format client "~A/~A/~A ~A:~A:~A~%" mon d y h m s)
64 (finish-output client))
66 (socket-connection-reset-error ()
67 (format t "Client reset connection!~%"))
69 (hangup ()
70 (format t "Client closed conection!~%")))
72 (format t "Sent!~%"))))
73 ;; ex-1e
75 ;; ex-2b
76 t))
77 ;; ex-2e
79 ;; ex-3b
80 ;; This is the main entry point into the example 3 server.
81 (defun run-ex3-server (&key (port *port*))
82 (handler-case
84 (run-ex3-server-helper port)
86 (socket-address-in-use-error ()
87 ;; Here we catch a condition which represents trying to bind to
88 ;; the same port before the first one has been released by the
89 ;; kernel. Generally this means you forgot to put ':reuse-addr
90 ;; t' as an argument to bind address.
91 (format t "Bind: Address already in use, forget :reuse-addr t?")))
93 (finish-output))
94 ;; ex-3e