これは fukamachi products advent calendar 2016 の13日目の記事です。ようやく折り返し地点ですね。

今日はwebsocket-driverについて話します。

小さなライブラリではありますが、その後の話の発端となるライブラリなので紹介します。

WebSocket

Clackにより通常のHTTP通信を行うWebアプリケーションは作れるようになりました。しかし、よりリアルタイム性の強いもの、たとえばチャットやゲームのようなアプリケーションを作るには貧弱です。

たとえばWebSocket。TCP上のプロトコルであり、通信時の不要なオーバーヘッドが少なく効率的でリアルタイム性の高い通信プロトコルです。

ClackでWebSocketを使う方法はなく、使えるとすればHunchensocketというHunchentoot拡張くらいでした*1。

Socket.IO

少しWebSocket周りの話もしておきます。

WebSocketの欠点は環境による通信状態の不安定さです。環境によってWebSocketが使えなかったり、使えてもすぐに切断されてしまったりします。この管理が難しくWebSocketの一般的な利用が妨げられているように思います。

この一つの解決策としてNode.jsのライブラリにSocket.IOというものがあります。

これはWebSocketが使えない環境のために通常のHTTP通信やHTTPのlong pollingなどで通信することもできます。最初はHTTPを試し、可能であればWebSocketに暗黙的にアップグレードします。ユーザー側もアプリケーション側も、何で通信しているのかということを意識せずに使えます*2。

Socket.IOはプロトコルが公開されているので、Common Lispのサーバー実装を作れば公式のフロントエンド実装と通信できるはずです。

ではこれを作ろうと思いました。Common Lispは高速ですし非同期WebサーバーのWookieもあり、言語としての特性を活かせそうです。

これを作るためにはまずはWebSocketから。WebSocketのサーバー実装とクライアント実装を作りました。それが「websocket-driver」です。

EventEmitter

websocket-driverのインターフェイスとして参考にしたのがNode.jsのEventEmitterです。

const EventEmitter = require('events'); class MyEmitter extends EventEmitter {} const myEmitter = new MyEmitter(); myEmitter.on('event', () => { console.log('an event occurred!'); }); myEmitter.emit('event');

on でイベントのコールバックを指定しておき、 emit で登録されているイベントコールバックを呼ぶものです。

ClackがPlackから実装をコピーしたように、websocket-driverも真似ています。Common Lispならばメソッドを使って handle-message などでもいいではないか、と思う人もいるかもしれませんが、イベント名が固定でない以上はこうするしかありません。

馴染んでいるのか何なのかまだわかりませんが、これはClackでWebSocketを使える唯一のライブラリです。

おわりに

websocket-driverはGitHubで公開されており、Starは28です。

明日のアドベントカレンダーは14日目のfast-httpについてです。お楽しみに。