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))
(setf (sb-bsd-sockets:sockopt-reuse-address *server*) t) (setf (sb-bsd-sockets:non-blocking-mode *server*) nil)
(sb-bsd-sockets:socket-bind *server* *address* *port*)
(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*)
(sb-bsd-sockets:socket-close *server*)
参考
- http://www.sbcl.org/manual/#Networking
- https://sinax.be/blog/lisp/programming-network-sockets-in-lisp.html
- https://yanqirenshi.hatenablog.com/entry/2016/12/05/SBCL_%E3%81%AE%E3%83%9E%E3%83%8B%E3%83%A5%E3%82%A2%E3%83%AB_14_Networking_%E3%82%92%E4%BF%AF%E7%9E%B0%E3%81%97%E3%81%A6%E3%81%BF%E3%82%8B%E3%80%82