with-open-passive-socket 改 ver 20110703
with-open-passive-socket を自作 - Shammerismで作成した with-open-socket を改良した。毎回 0.0.0.0 で listen するようになっていたが、listen-address を指定できるように改良。もともとの実装にSBCLで文字列をドット表記のIPアドレスに変換する - Shammerismの内容を加えた感じだ。
(defun open-socket-server (addr port) (let ((interface (handler-case (sb-bsd-sockets:make-inet-address addr) (error (e) (format t "~A was thrown. Use 0.0.0.0 as listen-address." (type-of e)) #(0 0 0 0))))) (handler-case (let ((server (make-instance 'sb-bsd-sockets:inet-socket :type :stream :protocol :tcp))) (sb-bsd-sockets:socket-bind server interface port) (sb-bsd-sockets:socket-listen server 400);400 is a backlog server) (sb-bsd-sockets:address-in-use-error () (format t "Address ~A:~A is already in use" interface port) (force-output) nil)))) (defmacro with-open-passive-socket (&rest body) (let ((server-symbol-value (caar body)) (server-listen-addr (cadar body)) (server-listen-port (caddar body))) `(let ((,server-symbol-value (open-socket-server ,server-listen-addr ,server-listen-port))) (unwind-protect (when ,server-symbol-value ,(cadr body)) (unless (null ,server-symbol-value) (format t "Close server socket...~%") (close-server-socket ,server-symbol-value))))))
使用する側は以下のような感じ。
(defun open-passive-server (addr port) (with-open-passive-socket (server addr port) (progn ... (open-passive-server "0.0.0.0" 7001)
progn まで macro の方に組み込みたいが、、、それはまた別の機会に。