with-open-passive-socket ver 20120327
with-open-passive-socket ver 20120322 を試す - Shammerismを見ていて、with-open-passive-socket の直下の do がどうしても気になり、、、do まで macro に含めてしまおう、ということでちょっとだけ書き直してみた。書き直したバージョンがこれ。
(defmacro with-open-passive-socket (&rest body) (let ((server-symbol-value (caar body)) (server-listen-addr (cadar body)) (server-listen-port (caddar body)) (main-body (cdr body))) `(let ((,server-symbol-value (open-socket-server ,server-listen-addr ,server-listen-port))) (unwind-protect (when ,server-symbol-value (do () (nil) ,@main-body)) (unless (null ,server-symbol-value) (format t "Close server socket...~%") (close-server-socket ,server-symbol-value))))))
まあ、do の部分を移動するだけなので大したことはない。使う側はちょっとだけシンプルになる。
(defun open-echo-server-v2 (addr port) (format t "> OpenEchoServer port open...~%") (with-open-passive-socket (server addr port) (let ((client (accept-client-socket server))) (unwind-protect (let ((receive-buffer (make-array 0 :fill-pointer 0 :adjustable t :element-type '(unsigned-byte 8)))) (do () (nil) (let ((b (read-byte client nil 'eof))) (cond ((eql 'eof b) (return)) (t (vector-push-extend b receive-buffer))) (format t "~A " b) (when (equal b 10) (return)))) (let ((received-message (decode-string-from-octets receive-buffer :external-format :utf-8))) (format t "~A~%" received-message) (when (string-equal received-message "quit") (format t "received quit...~%") (quit)))) (progn (format t "Close client...~%") (close-client-socket client)))))) (open-echo-server-v2 "0.0.0.0" 7001)
うーむ。。。クライアントをハンドルするところも macro にしてしまおうか。その方がよりすっきりするだろう。