clws

https://github.com/3b/clws.git

git clone 'https://github.com/3b/clws.git'

(ql:quickload :clws)
44

CLWS - a WebSocket server in Common Lisp

Currently requires SBCL or CCL, but shouldn't be too hard to port to other implementations/platforms supported by iolib.

Supports WebSocket draft protocols 7,8, and 13, and optionally 0.

Doesn't currently support wss: (TLS/SSL) connections, but proxying behind stud or stunnel should work.

Sample usage: Echo Server

First, set up a package:

(defpackage #:clws-echo
  (:use :cl :clws))

(in-package #:clws-echo)

Then we can start the websockets server, here we use port 12345:

(bordeaux-threads:make-thread (lambda ()
                                (run-server 12345))
                              :name "websockets server")

Next we need to define a ‘resource’, which we will call /echo (so we will connect with URIs like ws://localhost/echo). To do that, we subclass ws-resource and specialize a few generic functions on that class:

(defclass echo-resource (ws-resource)
  ())

(defmethod resource-client-connected ((res echo-resource) client)
  (format t "got connection on echo server from ~s : ~s~%" (client-host client) (client-port client))
  t)

(defmethod resource-client-disconnected ((resource echo-resource) client)
  (format t "Client disconnected from resource ~A: ~A~%" resource client))

(defmethod resource-received-text ((res echo-resource) client message)
  (format t "got frame ~s from client ~s" message client)
  (write-to-client-text client message))

(defmethod resource-received-binary((res echo-resource) client message)
  (format t "got binary frame ~s from client ~s" (length message) client)
  (write-to-client-binary client message))

Finally, we register the resource with the server, and start a thread to handle messages for that resource:

(register-global-resource "/echo"
                          (make-instance 'echo-resource)
                          (origin-prefix "http://127.0.0.1" "http://localhost"))

(bordeaux-threads:make-thread (lambda ()
                                (run-resource-listener
                                 (find-global-resource "/echo")))
                              :name "resource listener for /echo")

Configuration variables

Resource handler API

Sending data to clients

Getting information about connected clients

(most of these should be treated as read-only, and any visible setf functions may go away at some point)