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.
16 (defun run-ex3-server-helper (port)
18 (server :connect
:passive
19 :address-family
:internet
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~%"
38 ;; keep accepting connections forever.
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
47 (multiple-value-bind (who rport
)
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
)
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.
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!~%"))
70 (format t
"Client closed conection!~%")))
72 (format t
"Sent!~%"))))
80 ;; This is the main entry point into the example 3 server.
81 (defun run-ex3-server (&key
(port *port
*))
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?")))