0

RocketIOのJSライブラリ作った

Webブラウザ拡張等からRocketIOのサーバーに接続したい時などに使う。


RocketIOと同じリポジトリにある。
shokai/sinatra-rocketio · GitHub


ダウンロード
rocketio.js
rocketio.min.js


connect関数に接続先のURLを渡せば勝手にwebsocketかcometで接続してくれる。

<script src="//ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
<script src="/rocketio.min.js"></script>
var io = new RocketIO().connect("http://example.com");

io.on("connect", function(){
alert(io.type + " connect!! " + io.session);
});
あとは使い方は同じ。


これを使うときは、Sinatra側でcometのクロスドメインを許可しておく。

config.ru
require 'sinatra'
require 'sinatra/rocketio'
set :cometio, :allow_crossdomain => true
set :rocketio, :websocket => true, :comet => true # enable WebSocket and Comet

run Sinatra::Application

0

Ruby上に並列言語拡張Lindaを実装してWebSocket/Cometで使えるようにした

gemにしてある

linda | RubyGems.org | your community gem host

Linda

Lindaは1990年ごろに出来た言語。
タプルスペースという共有メモリ空間でタプル(オブジェクト)を共有して、in/out/rd/inp/rdpという命令で操作する事で大抵の並列処理が記述できるという物。
仕様は単純なんだけどセマフォなどのロック機構やジョブキューも超簡単に記述できる。いわば分散並列処理のための最小セット。

既にCやJavaの実装があり、Rubyでも咳さんのRindaがある。

で、今回作ったLinda gemではタプルのマッチング判定とオンメモリのタプルスペースの読み書き機能と、それぞれのテストコードしか実装されていない。
複数のプロセスからタプルスペースに接続して読み書きする機能は実装されていない。
マッチングは配列タプルは要素の前方一致、Hashタプルは自身のKeyとValueが相手に全部含まれていればtrueとしている。


Linda RocketIO

Linda gemをさらにSinatra::RocketIOに乗せた。
RocketIOはSocket.ioをパクって俺が作ったSinatra用のWebSocket/Comet実装です。
sinatra-rocketio-linda | RubyGems.org | your community gem host

Sinatraがタプルスペースつまり共有メモリ空間になって、RocketIOで接続されたクライアントがLindaで操作できる。
今のところRubyとJavaScriptがタプルの読み書きに参加できる。

命令はin/out/rd/inp/rdpがそれぞれtake/write/read/take(コールバック)/read(コールバック)になった。
RocketIOは非同期通信なので全部非同期で実行される。


LindaBase

Webサービスを作った。LindaBaseという。
http://linda.shokai.org/
http://linda.masuilab.org/
http://linda-base.herokuapp.com/
それぞれ物理的に別のサーバーだけどアプリは同じ。
ソースコードは http://github.com/shokai/linda-base
自分のサーバーやHerokuなどにインストールも簡単にできる。



いくつかサンプルアプリを作った。
世界観的にはユビキタスコンピューティング、つまり生活環境にセンサーやコンピュータが埋め込まれていて陰ながら色々サービスしてくれるし、スマホとかで操作もできるしWebサービスとも連携したりする環境を考えている。


しゃべる

http://linda.shokai.org/myhome/say/hello
タプル[“say”, “hello”]をタプル空間”myhome”に書き込むページ。
https://github.com/shokai/linda-mac-say
[“say”, 文字列] をwatchして、Macのsayコマンドに投げるアプリ。タプル[“say”, String, “success”]を書き込む。
Rubyで書かれていて、適当なMac上で起動してlinda.shokai.orgに接続して使う。


温度や明るさをArduinoでセンシング、寒かったら警告など

http://linda.shokai.org/myhome/sensor
タプル空間”myhome”内の[“sensor”]から始まるタプルがwatchできるページ。
https://github.com/shokai/linda-arduino-sensor
Arduinoに接続した照度と気温センサーを読んで、タプル[“sensor”, “light”, 120]と[“sensor”, “temperature”, 25]をwriteするアプリ。毎秒書き込む。
適当なUNIXマシンで動かして、linda.shokai.orgに接続して使う。(以降のgithubはlindaに接続して使うアプリです)
https://github.com/shokai/linda-temperature-alert
気温をアラートする。タプル[“sensor”, “temperature”]をreadして、タプル[“say”, “現在の気温 23度”]や[“say”, “現在の気温 8度、お体に障りますよ”]などの警告を流すアプリ。


スマホとPhidgetsサーボモータでドアロックを開ける

http://linda.shokai.org/myhome/door/open
タプル[“door”, “open”]をタプル空間”myhome”に書き込むページ。
https://github.com/shokai/linda-door-phidgets-servo
タプル[“door”, “open”]が来たら、Phidgetsのサーボモータを使ってドアの錠を回す。タプル[“door”, “open”, “success”]を書き込む。
https://github.com/shokai/linda-door-open-goldfish
タプル[“door”, “open”]をAjax POSTとGoldFishで書き込む例


Twitter

http://linda.shokai.org/myhome/twitter/tweet/hello
タプル[“twitter”, “tweet”, “hello”]をタプル空間”myhome”に書き込むページ。
https://github.com/shokai/linda-twitter
タプル[“twitter”, “tweet”, 文字列]をwatchして、Tweetするアプリ。


このように共有メモリを介して小さいアプリが連携できる事がおわかりか。
URLがタプル空間名/タプルの内容になっていて、その場でダミーデータを投入できたり通信を見たりできるのもとても便利。


利点

最後にこのシステムの利点をまとめておく。

分散並列プログラミングがシンプルに書ける

4種類の命令の組み合わせで何でもできる。共有メモリに接続して読み書きするだけ。
ユビキタスコンピューティング、特にお家ハック系はノード間の連携がとても多い。
センサAが反応してから→センサBの反応を待って→モーターCを動かす、のようなプログラムは常人にはなかなか難しい。
Linda使うと簡単。


拡張が簡単

全通信が覗き見できる。処理をフックできるとも言えるし、最初からLinda全体がプラグインシステムみたいになっている。
“明るくなったら”→”カーテンを開ける”というシステムをLinda上に作った後で、”明るくなったら”→”ご飯を炊く”というシステムを追加したいとする。
共有メモリなので、太陽が出た[“sun”, “available”]というタプルを監視すればご飯が炊ける。
Lindaを使わずに明るさセンサとカーテンを直結した場合、ご飯炊くプログラムがデータを取得するには明るさセンサのプログラムを修正しなければならない。
最初からLindaを使っていれば、既存システムを一切修正せずに拡張できる。


デバッグが楽

“明るくなったら”→”カーテンを開ける”というシステムが動かなくなった場合
\突然の死/
明るさセンサとカーテンを直結していた場合、どこが悪いかわからない。
通信がwebページで見れるので、どの部分が壊れたか特定しやすい。


分担して同時にシステムを作れる

普通のシステムでは、センサー側を先に作成しなければアクチュエータ側を作れない。
入力値が無いと出力側を作れないのだが、LindaBaseのwebページ上でダミーデータを投入できる。
ボタン押すだけでタプルが書き込める
入力側が未完成でも、出力側を実装できる。


接続を確立し、維持するのが楽

RocketIOを使っているのでWebSocketで高速な通信ができる。
WebSocketが使えない環境の場合、自動的にcometで接続される。
サーバーより先にクライアントが起動しても、クライアントは自動的に接続をリトライする。
e-mobileの一番下のプランとか海外の怪しい回線でも多分動くので、海外での学会展示でも有用な気がする。
どちらを使っているかは全く意識せずok
切断されても自動再接続される。


オブジェクトが送れる

タプル、実は配列だけではなくHashも送れる。
配列の入れ子も送れるし、複雑なデータ構造も送れる
[“door”, [“open”, “stop”, “close”], {speed: 30, delay: 1}] とか
JSONに変換できる物なら何でも送れる。


なぜLindaというgemがあるか

タプルのマッチングと、オンメモリのタプルスペースの操作APIとそのテストだけが書かれたgemを作ったのは
DBやファイルシステム上で互換のある物を作ればLinda RocketIOで使うLinda実装を差し替えれるようにしたかったから。(まだその機構作ってない)
一応MongoDBで実装してみる予定。


色々便利なのでモリモリ開発していきます。

0

Macにnginx入れてwebsocket proxyした

これが参考になった
nginxを1.3.14にしたらWebSocketがProxyできた
config-com.favorymous.www.conf


おかげで家のMacでRocketIOのcomet/websocketチャットが動いた
http://chat.shookai.org/
サブドメインで判別してアプリにproxyしている。

経緯

ほぼ同時に研究室のサーバーが壊れたり、家のファイルサーバーが壊れたりしたのでMacとか色々環境を再構築することになった。

昔研究室のマシンをセットアップした時はみんなRubyしか使ってなかったので、Apache+Passengerにしておいたけど
最近はNodeとかWebSocketとかアプリプロセス内に小さなworker持ったりとかするようになって、Apache+Passengerでは無理になったので

nginxを前に置いて、後ろのアプリ(たくさん、ユーザー権限で動く)にproxyする事にした。
(アプリはforemanなどでlaunchdにインストールする)


インストール

brew info nginx
brew install nginx --devel
develなら、変なことしなくてもwebsocket proxyが使える1.3.14がインストールできる。


起動
nginx
http://localhost:8080 で起動している事を確認。
root権限でないと80番では起動できない。

終了
nginx -s stop

launchd 起動ファイルをコピー
サービスとしてlaunchdにインストール
cp /usr/local/Cellar/nginx/1.3.14/homebrew.mxcl.nginx.plist ~/Library/LaunchAgents/
launchctl load -w ~/Library/LaunchAgents/homebrew.mxcl.nginx.plist

アンインストール
launchctl unload ~/Library/LaunchAgents/homebrew.mxcl.nginx.plist
brew uninstall nginx


設定する

設定ファイルはここにある
/usr/local/etc/nginx/nginx.conf

編集して、有効にするにはnginxを再起動しなければならないが
設定のシンタックスだけチェックもできる。エラーメッセージもわかりやすい。
nginx -t


nginxからwebsocket使ってるアプリにproxy


まずSinatra RocketIOで作ったwebsocketアプリでチャットするアプリを、HTTP port 5000 / websocket port 33100で動かしてある。
これ shokai/rocketio-chat-sample · GitHub


nginx.confのhttp{ }の中にupstreamとserverを書く
chat.shokai.org へのアクセスを http://127.0.0.1:5000 に流す。
  upstream rocketio-chat {
server 127.0.0.1:5000;
}

server {
listen 8080;
charset utf-8;
server_name chat.shookai.org;
root /Users/sho/projects/rocketio/rocketio-chat-sample/public;
location / {
try_files $uri $uri/index.html $uri.html @rocketio-chat;
}
location @rocketio-chat{
proxy_read_timeout 300;
proxy_connect_timeout 300;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-Host $host;
proxy_set_header X-Forwarded-Server $host;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header X-Document-Root $document_root;
proxy_set_header X-Document-URI $document_uri;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
proxy_pass http://rocketio-chat;
}
}

nginx再起動すると、cometもwebsocketも通っていた。


設定はgithubで管理することにした
shokai/shookai.org.nginx.conf · GitHub


最終的に、 /usr/local/etc/nginx/apps/アプリ名.conf を作ればどんどん増やせるようにした。
これをテンプレとする。
upstream rocketio-chat {
server 127.0.0.1:5000;
}

server {
listen 8080;
charset utf-8;
server_name chat.shookai.org;
root /Users/sho/projects/rocketio/rocketio-chat-sample/public;
location / {
try_files $uri $uri/index.html $uri.html @rocketio-chat;
}
location @rocketio-chat{
include includes/proxy.conf;
proxy_pass http://rocketio-chat;
}
}

0

Sinatra RocketIOでお絵かき共有作った

横浜から電車に座れたので、学校行くまでの間にスマホやタブレットやPCで同時に絵を描けるやつをcanvasとSinatra RocketIOで作った。
一瞬でできた。RocketIOの生産性はヤバイ。

デモ http://canvas.shokai.org/ch1
URL末尾がRocketIOのチャンネルになっていて、同じURLを開けばどのブラウザからでも同じ絵が同時に編集できる。


Nexus7で絵を描いてMacでgyazoすると便利。


チャンネルは http://canvas.shokai.org/shokai
とか http://canvas.shokai.org/hogehoge
とか好きなだけ増やせる。


ソースコード
shokai/rocketio-canvas · GitHub


デモなので突然止めたりしますが、ソースをgit cloneしてきてbundle installしてrackupすればRuby1.8でも2.0でも動くのでどうぞ。

ご意見ご要望などあったらissueやtwitter @shokaiへ


実装はとても簡単で、一番面倒だったのはcanvasをスマホでもPCでも使えるようwrapするjs部分だった。
DBは使っていない(オンメモリ)

READMEやGemfile含めて300行ちょっとで完成した。

% git ls-files | xargs wc -l
       4 .gitignore
7 Gemfile
77 Gemfile.lock
1 Procfile
31 README.md
8 config.ru
50 main.rb
62 public/canvas.js
40 public/index.js
51 views/index.haml
331 total

0

RocketIO Hello World作った

チャットのサンプルがあれば使い方わかるかな、と思ったけどまだ難しいらしいので

もっとミニマムなサンプルアプリを作ってみた。


ブラウザを2つ開いてボタン押すと動く。
dev.shokai.org:4100


ソースコード
shokai/rocketio-hello-world · GitHub


サーバーとJS、これだけで実装できるので便利じゃないですかね?