Shammer's Philosophy

My private adversaria

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 にしてしまおうか。その方がよりすっきりするだろう。