« ^ »

Common Lisp(SBCL)でのソケットプログラミング

所要時間: 約 2分

Common LispにはBSDソケットプログラミングの仕様は決められていない。 そのためCommon Lispの処理系がそれぞれにソケットプログラミングのAPIを実装している。 今回はCommon Lisp実装系の1つであるSBCLを用いることにした。 SBCLはCommon Lispn実装系のなかでは人気の高い実装である。 SBCLではBSDソケットのためのAPIをsb-bsd-socketsモジュールで実装している。

それぞれの実装系を横断できるように差を吸収してくれるusocketsというライブラリも存在するが 今回はなるべくプリミティブな関数にアクセスしたかったので sb-bsd-socketsモジュールをそのまま使うことにした。

以下ではsb-bsd-socketsモジュールを用いたソケットプログラミングの方法の基礎的な部分を示す。

sb-bsd-socketsモジュールを用いたソケットプログラミング

(defparameter *port* 8080)
(defparameter *address* #(0 0 0 0))
事前準備
(setq *server* (make-instance 'sb-bsd-sockets:inet-socket :type :stream :protocol :tcp))
socketを作成する
(setf (sb-bsd-sockets:sockopt-reuse-address *server*) t)
(setf (sb-bsd-sockets:non-blocking-mode *server*) nil)
socketの値を設定する
(sb-bsd-sockets:socket-bind *server* *address* *port*)
socketを開く
(sb-bsd-sockets:socket-listen *server* 1)
接続を待つ
(setq *conn* (sb-bsd-sockets:socket-accept *server*))
接続を受け入れる
(multiple-value-bind (buffer length)
    (sb-bsd-sockets:socket-receive *conn* nil 1024)
  (setq *buffer* buffer)
  (setq *length* length))
データを読み出す
(subseq *buffer* 0 *length*)
読みだしたデータを切り詰める
(sb-bsd-sockets:socket-send *conn* "aaaaaaaaa" nil)
データを送信する
(sb-bsd-sockets:socket-close *conn*)
受け入れたsocketを閉じる
(sb-bsd-sockets:socket-close *server*)
serverとして開いているsocketを閉じる