Shammer's Philosophy

My private adversaria

LispでSocket送受信その2

一方的にメッセージを送るだけのクライアントと、受けたメッセージを表示してそのまま終了するサーバをサンプルとして作った(2011/01/11の記事)が、それを一歩進めて、サーバーは受け取ったメッセージをクライアントに送り返してから終了し、クライアントはその受け取ったメッセージを表示して終了する、というように改良してみた。

サーバー側の実装は以下のような感じ。

(defun open-echo-server (port)
  (let ((server (make-socket
		 :type
		 :stream
		 :connect
		 :passive
		 :local-host "localhost"
		 :local-port port)))
    (let ((client-socket (accept-connection server)))
      (format t "> Server received a message: ~%")
      (loop
	   (let ((char (read-char client-socket nil nil)))
	     (if (eql (char-code char) '10) (return))
	     (format t "~a~%" char)
	     (format client-socket "~a" char)))
      (force-output client-socket)
      (close client-socket))
    (close server)))

クライアント側の実装は以下のような感じ。

(defun send-message (destination-host destination-port message)
  (let ((client (make-socket
		 :address-family
		 :internet
		 :type
		 :stream
		 :connect
		 :active
		 :remote-host destination-host
		 :remote-port destination-port)))
    (format client message)
    (format client "~%")
    (force-output client)
    (loop
       (let ((char (read-char client nil nil)))
	 (if (null char) (return))
	 (format t "~a~%" char)))
    (close client)))

サーバ側は、クライアントからのデータは改行までなので、受け取った文字(データ)がASCIIの10であったら読み込みを終了するようにしてみた。逆に、クライアント側は、サーバからNILを受け取ってエラーになったので、読み込んだデータがNILかどうかのチェックを行っている。Javaと違って、InputStreamとOutputStreamは隠蔽されているんだな。Socketに対して、読み込むか書き込むかの違いになっているんだ。個人的にはこっちの方が好きだな。