Shammer's Philosophy

My private adversaria

sbcl で Socket を使う

いろいろなサイトで情報を収集。とりあえず、(require :sb-bsd-sockets) を事前に実行しておく必要がある。以下、clozure と汎用性を持たせるために汎用関数を独自に定義。

(defun open-socket-server (port)
  (let ((interface #(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))))

(defun accept-client-socket (server)
  (sb-bsd-sockets:socket-accept server))

(defun make-socket-stream (socket)
  (sb-bsd-sockets:socket-make-stream socket :output t :input t :element-type '(unsigned-byte 8)))

(defun close-server-socket (server)
  (sb-bsd-sockets:socket-close server))

(defun close-client-socket (client)
  (sb-bsd-sockets:socket-close client))

とりあえず、これでいいだろうか。socket を作成してから、stream をそこから取り出す、というのは clozure とは違う点だ。element-type に何を指定するかで読み出すデータも変化してくるようだ。文字列の扱いとかもこの点を意識する必要がありそうだ。