やったことだけ書く備忘録

nodejsのWebSocket-Serverに色んな方法で外部からブロードキャストする方法

久々のnode.jsです。node.jsと言えばgruntとかが有名になっちゃって、WebSocketとかソンナノアッタネ状態なわけですが、久々にちょろっと触ってて解決したところがあったのでメモメモ。

WebSoketの利用ポイントがあんまり…


WebSocketは確かに面白いです。リアルタイムです。でもクライアント側が限定されたり、さらにはnode.js側のnpmの対応とかみると、そこまでガチなロジックアプリケーションにはまだ使えないかなーって個人的には思ってます。実際、サンプルアプリもチャットとかそんなのばかりですしね。



ブロードキャスト専用のプロセスとして使う


なので、メッセージをブロードキャストして受け取る機構として使おうかなと思った次第です。サポートされていなければメッセージを受けとらないだけで、別段クリティカルな部分じゃない所で動かせばいいかなーと思いました。まぁメッセージが受け取れないと「○○さんがログインしました」とか分からないのでぼっちになるかもしれないですね。Chromeとか使いましょうね。



WebSocketのサーバに外部プロセスからメッセージを送ってブロードキャストする


というのが今回のお題です。node.jsでWebSockt動いて(∩´∀`)∩ワーイってなったあと、これメッセージングとかクライアントからしか送れないじゃんとなってうーんとなりました。例えば、ログインとかカートに入れる処理をnode.jsで書きますか?僕は現時点では書きません。PHPとかでやると思います。

で、PHPでログインやカートに入れたメッセージをWebSocketから配信したいんです。通常なら、

ログインする(サーバ)→成功した(クライアント)→成功メッセージ送信→ブロードキャスト(WS)

とい流れなのですが、

ログインする(サーバ)→成功メッセージ送信→ブロードキャスト(WS)

としたいわけです。サーバからWebSocketにメッセージングできれば便利ですよね。



というわけで実装


ようやく本題です。どうするかというと、node.jsでWebSocketのサーバを起動したのと同じスコープで、UDPサーバとUNIXソケットもlistenして、そのメッセージをそのままWebSocketから配信するだけです。ちなみにHTTPからはブロードキャストしません。誰かが勝手にメッセージングしちゃいますもんね。コードは以下です。




var WebSocket = require('websocket').server,
    
Net       = require('net'),
    
http      = require('http'),
    
Dgram     = require('dgram'),
    
unixPath  '/tmp/wsbroadcaster.sock',
    
unixSocket,
    
udpSocket,
    
wsServer,
    
httpServer;

// Create HTTP Server
httpServer http.createServer(function(requestresponse) {
  
response.writeHead(404, {"Content-Type"'text/plain'});
  
response.write('Page Not Found.');
  
response.end();
});
httpServer.listen(8124);

// Create WebSocket Server
wsServer = new WebSocket({
  
httpServer:            httpServer,
  
autoAcceptConnectionstrue
});

// WebSocket events
wsServer.on('connect', function(connection) {
  
console.log('WebSocket connected.');
  
connection.on('message', function(msg) {
      
wsServer.broadcast(msg);
  })
});

// Create udp Socket
udpSocket Dgram.createSocket('udp4');

udpSocket.on('message', function(messageinfo) {
  
console.log('UDP request handled.');
  
wsServer.broadcast(message.toString('utf8'0info.size));
});

udpSocket.on('listening', function() {
  
console.log('UDP Server bound at ' udpSocket.address().address ':' udpSocket.address().port);
});

udpSocket.bind(8125); // listening 0.0.0.0:8125

// Create Unix Socket
unixSocket Net.createServer(function(connection) {
  
console.log('UNIX Socket handled.');
  
connection.setEncoding('utf8');
  
connection.on('data', function(chunk) {
    
wsServer.broadcast(chunk);
  });
})
unixSocket.listen(unixPath, function() {
  
console.log('UNIX Socket bound.');
  
// do something for listen started.
});

// SIGINT Event bind
process.on('SIGINT', function() {
  
udpSocket.close();
  
unixSocket.close();
  
process.exit();
});
 


gistにあげておきました。




https://gist.github.com/4317759




UDPサーバはdgramというモジュールから起動、UNIXドメインソケットはnetモジュールから起動できるみたいです。あとは、それぞれをlisten/bindしたら、メッセージを受け取った段階でwsServerからbroadcast()するだけです。
あ、UNIXドメインソケットはCtrl-Cで中断すると接続が残っちゃうみたいなので、SIGINTのシグナルイベントでcloseするようにします。そうしないと二回目が起動できなくなります。



メッセージ送ってみる


ではサーバサイドからメッセージ送ってみます。Rubyだとこんな感じでしょうか。




#!/usr/bin/ruby

require "socket"

// UNIXドメインソケットを通してメッセージを送る
UNIXSocket.open('/tmp/wsbroadcaster.sock') { | socket |
  
socket.puts('Hello, socket!')
}
 


外部IPの場合はUDPで送りましょう。netcatコマンドで送れるので、cronで定期監視→メッセージングとかできて、死活監視の情報配信とかにいいかもしれませんね。




$ echo "仕事しろ" nc --4 xxx.xxx.xxx.xxx 8125
 


これで社内のみんなにブロードキャストできますね!



まとめ


使い所は限定されますが、定期的に何かを監視したり、特定の操作を行ったタイミングでメッセージングしたいケースってあるかと思いますGrowlとかそうですね。クライアント側で表示方法を考えれば、面白いことに使えるかもしれませんね。




ただ、実戦投入はもう少し先の話だと思いますが…

« 前の記事 次の記事 »

3件のコメント

Jane さん

All of my questions selhted-ttanks!

Kenisha さん

Kewl you should come up with that. Exncellet! http://zqvayd.com [url=http://ltkjagdeyvd.com]ltkjagdeyvd[/url] [link=http://ktqccf.com]ktqccf[/link]

My Homework Now さん

cover letter help <a href="http://coverletters.store">cover letters</a> cover letters <a href=http://coverletters.store>cover letters</a>

コメントを投稿する

 画像に表示されている文字を入力してください。