client socket handling macro
with-open-passive-socket ver 20120327 - Shammerismの処理では accept したクライアントの処理を普通に書いていたが、
- accept される
- read する
- close する
という一般的すぎる流れ。read の直後の処理はケースバイケースかもしれないが、accept されるところと close するところはもう定型なので、これを macro にしてしまう。
(defmacro handle-accept-connections (&rest body) (let ((server-symbol (caar body)) (client-symbol (cadar body)) (actions (cdr body))) `(let ((,client-symbol (accept-client-socket ,server-symbol))) (unwind-protect (progn ,@actions) (close-client-socket ,client-symbol)))))
これを使って echo-server を再定義。
(defun open-echo-server-v2 (addr port) (format t "> OpenEchoServer port open...~%") (with-open-passive-socket (server addr port) (handle-accept-connections (server client) (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)))))))
データの読み込みまで macro でもいいのかもしれない。binary データお読み込むものと ascii データを読み取るもの、2 パターン書いてみようか。。。