RosettaCodeData/Task/Echo-server/Common-Lisp/echo-server-3.lisp

48 lines
2 KiB
Common Lisp
Raw Permalink Normal View History

2013-10-27 22:24:23 +00:00
(defvar *clients* '()
"This is a list of (socket :input status) which is used with
`socket:socket-status' to test for data ready on a socket.")
2013-04-10 16:57:12 -07:00
2013-10-27 22:24:23 +00:00
(defun echo-server (port)
"Listen on `port' for new client connections and for data arriving on
any existing client connections"
(let ((server (socket:socket-server port)))
(format t "Echo service listening on port ~a:~d~%"
(socket:socket-server-host server)
(socket:socket-server-port server))
(unwind-protect
(loop
(when (socket:socket-status server 0 1)
(echo-accept-client (socket:socket-accept server
:external-format :dos
:buffered t)))
(when *clients*
(socket:socket-status *clients* 0 1)
(mapcar #'(lambda (client)
(when (eq :input (cddr client))
(echo-service-client (car client)))
(when (eq :eof (cddr client))
(echo-close-client (car client)))) *clients*)))
(socket-server-close server))))
2013-04-10 16:57:12 -07:00
2013-10-27 22:24:23 +00:00
(defun echo-accept-client (socket)
"Accept a new client connection and add it to the watch list."
(multiple-value-bind
(host port) (socket:socket-stream-peer socket)
(format t "Connect from ~a:~d~%" host port))
(push (list socket :input nil) *clients*))
2013-04-10 16:57:12 -07:00
2013-10-27 22:24:23 +00:00
(defun echo-service-client (socket)
(let ((line (read-line socket nil nil)))
(princ line socket)
(finish-output socket)))
2013-04-10 16:57:12 -07:00
2013-10-27 22:24:23 +00:00
(defun echo-close-client (socket)
"Close a client connection and remove it from the watch list."
(multiple-value-bind
(host port) (socket:socket-stream-peer socket)
(format t "Closing connection from ~a:~d~%" host port))
(close socket)
(setq *clients* (remove socket *clients* :key #'car)))
2013-04-10 16:57:12 -07:00
2013-10-27 22:24:23 +00:00
(echo-server 12321)