WebSocket勉強会
WebSocket Communication
自己紹介
- かみやん (Twitter@kamiyam)
- システム開発会社

- ほとんどWebのシステム
- Java・C#がメインのプログラマ
- 元自動車整備士です
アジェンダ
- WebSocketとは?
- 現状WebSocketで何ができるのか?
私のセッションでは難しい話は抜きにしてWebSocketを使ったデモを中心にお送りしたいと思います。
と、事前資料公開時は考えていましたが、デモだけで30分もたないのでWebベースの実装についての解説なども
WebSocketとは?
今日、何度も出てきたと思いますが、リアルタイムに双方向通信を可能にするプロトコルです。
WebSocketが(現時点で)使えるブラウザ
- PC
- Chrome4 / Safari5
- iPhone / iPad
- iOS 4.2.1 Safari
WebSocket実装状況
ちなみにFireFox4 beta7 / Opera 10.2.0ではWebSocketを利用出来ましたが、FireFox4 / Opera11 ではWebSocketは無効化されています。
- 参考
- WebSocket実装状況
- Firefox 4 では Websocket を無効化します « Mozilla Developer Street (modest)
- https://dev.mozilla.jp/hacksmozillaorg/websockets-disabled-in-firefox-4/
- こてさきAjax:WebSocketがデフォルトdisableとなった件
- http://blog.livedoor.jp/kotesaki/archives/1600864.html
HTTPプロトコルイメージ
- Ajax(httpリクエスト)は都度コネクションを貼り、レスポンスを待つ

WebSocketプロトコルイメージ
- WebSocketは一度コネクションを貼ると、通信をそのWebSocketコネクション上でやり取りする

都度コネクションを貼る必要が無くなるので、結果通信ロスが減る
アンケート
WebSocketについて、どれに興味がありますか?
クライアント実装
ブラウザからのWebSocket通信
クライアント実装
- 一度httpプロトコル(要は普通にブラウザ)で画面表示
- javascriptからwebsocketオブジェクトをURL指定で生成
- httpの場合の接続先:『ws://exsample.com』
- httpsの場合の接続先:『wss://exsample.com』
- クライアント側はこれだけでサーバとの双方向通信が可能になります
- (今後の仕様しだいでは認証が必要)
クライアント実装(JavaScript)
<script type="text/javascript">
var protocol = ( location.protocol == "https:" ) ? "wss" : "ws";
var url = protocol + "://" + "exsample.com";
var websocket = new WebSocket( url );
//WebSocketのイベントの登録
websocket.addEventListener( "open", openFunc, false );
websocket.addEventListener( "close", closeFunc, false );
websocket.addEventListener( "message", receiveMessage, false );
//送信イベント
getElementById("button").addEventListener( "click", sendMessage, false );
//message送信
function sendMessage()
{
websocket.send( "送信する文字列とかJSONとか" );
}
//message受信
function receiveMessage( msg )
{
alert ( msg.data );
}
</script>
SyncSlideでのクライアント実装
- ブラウザ間でスライドコマンドを共有
- iPhone/iPadでは jQueryを使ってタッチイベントをコマンドとして処理

- up → websocket.send( "top" )
- left → websocket.send( "prev" )
- right → websocket.send( "next" )
- down → websocket.send( "last" )
クライアント実装(タッチイベント処理)
//iphoneタッチ処理
var slider = document.getElementById( "slide" );
slider.addEventListener( "touchstart", touchEvent, false );
slider.addEventListener( "touchmove", touchEvent, false );
slider.addEventListener( "touchend", touchEvent, false );
function touchEvent( e ){
//スワイプ伝播キャンセル
e.preventDefault();
//シングルタッチのみ取り出す
var touch = e.touches[0];
if ( e.type == "touchstart" ){
//移動開始場所の設定と移動距離の初期化
}
else if ( e.type == "touchmove" ){
//移動距離を計算
}
else if ( e.type == "touchend" ){
//縦横判定からoperetionを設定
var operation = "top";
//処理送信
sendMessage( operation );
}
}
jQueryライブラリを使ったマルチタッチイベント
当初は自前で移動距離等で判定していましたが、今回からjQueryのライブラリを使いました。
- TouchSwipe
- http://plugins.jquery.com/project/touchSwipe
TouchSwipe
//シングルタッチ定義
var singleSwipeOptions = {
swipe:singleSwipe, //関数名
threshold:50, //移動距離閾値
fingers:1 //タッチ本数
}
//ダブルタッチ定義
var doubleSwipeOptions = {
swipe:doubleSwipe,
threshold:50,
fingers:2
}
//iphone用スワイプイベント
$( "#slide" ).swipe( singleSwipeOptions );
$( "#slide" ).swipe( doubleSwipeOptions );
//一本指スワイプ
function singleSwipe( event, direction )
{
var message = "";
if( direction === "up" ) message = "first";
else if( direction === "left" ) message = "prev";
else if( direction === "right" ) message = "next";
else if( direction === "down" ) message = "last";
if( message !== "" ) sendMessage( message );
}
//二本指スワイプ
function doubleSwipe( event, direction )
{
if( direction === "up" ) hoge();
else if( direction === "left" ) fuga();
else if( direction === "right" ) hogohoge();
else if( direction === "down" ) fugafuga();
}
サーバーサイド実装
WebSocketエコーサーバー
WebSocketが使えるサーバ
- Python
- Apache + mod_pywebsocket
- Java
- Jetty
- JavaScript
- node.js + socket.io
今回使用したWebサーバー

Jetty
- Jetty
- http://www.eclipse.org/jetty/
- Javaで実装されたServletコンテナ / HTTPサーバ
- ライセンス
- Apache License Version 2.0のもとオープンソースソフトウェアとして公開
- 特徴
- 軽量で高速に動作する
ちなみにGAE/J(Google App Engine / Java)では Jettyが採用されています。
WebSocketは使えませんが、サーバからPushを行う仕組みとしてChannel APIが提供されています。
サーバーサイド実装
Jetty7を使ったWebSocket通信
- 言語 / サーバ
- Java / Jettty7
- 実装
- サイトのディレクトリごとにコネクショングループを作る
- 受け取ったスライドコマンド(JSON)をグループ全員に送信する
- クライアントから送られたメッセージをそのまま他のクライアントに渡す簡単なエコーサーバ
- JSONメッセージの処理にはJSONICというライブラリを利用しています。
WebSocketイベント処理
WebSocketインターフェース
クライアントの操作に応じて"onHogeHoge"が呼ばれる(イベント駆動)
※jetty-websocket-7.4.1.v20110513.jarより
package org.eclipse.jetty.websocket;
import java.io.IOException;
public interface WebSocket
{
void onOpen(Connection connection);
void onClose(int closeCode, String message);
interface OnTextMessage extends WebSocket
{
void onMessage(String data);
}
interface OnBinaryMessage extends WebSocket
{
void onMessage(byte[] data, int offset, int length);
}
interface OnControl extends WebSocket
{
boolean onControl(byte controlCode,byte[] data, int offset, int length);
}
interface OnFrame extends WebSocket
{
boolean onFrame(byte flags,byte opcode,byte[] data, int offset, int length);
void onHandshake(FrameConnection connection);
}
public interface Connection
{
String getProtocol();
void sendMessage(String data) throws IOException;
void sendMessage(byte[] data, int offset, int length) throws IOException;
void disconnect();
boolean isOpen();
void setMaxTextMessageSize(int size);
void setMaxBinaryMessageSize(int size);
int getMaxTextMessageSize();
int getMaxBinaryMessageSize();
}
public interface FrameConnection extends Connection
{
boolean isMessageComplete(byte flags);
void close(int closeCode,String message);
byte binaryOpcode();
byte textOpcode();
byte continuationOpcode();
byte finMask();
boolean isControl(byte opcode);
boolean isText(byte opcode);
boolean isBinary(byte opcode);
boolean isContinuation(byte opcode);
boolean isClose(byte opcode);
boolean isPing(byte opcode);
boolean isPong(byte opcode);
void sendControl(byte control,byte[] data, int offset, int length) throws IOException;
void sendFrame(byte flags,byte opcode,byte[] data, int offset, int length) throws IOException;
}
}
JSONICを使ったJSON→POJO(Plain Old Java Object)変換サンプル
public void sample(){
//ブラウザから渡されたJSON文字列
String jsonMsg = "{hoge:\"fuga\",foo:\"bar\",name:\"kamiyam\",num:5}";
//Informetionクラスに変換
Informetion info = JSON.decode( jsonMsg, Informetion.class );
//逆も簡単にできます (infoオブジェクトからJSON文字列に変換)
String temp = JSON.encode( info );
System.out.println( temp );
//{hoge:\"fuga\",foo:\"bar\",name:\"kamiyam\",num:5}
}
まとめ
- WebSocketは双方向通信を実現するプロトコル
- ブラウザベースよりスマートフォンアプリの方が広がりがあるのではないか?
- リアルタイムWeb
ご清聴ありがとうございました
〜 お疲れ様でした 〜
Special thanks! mukiSlide is made by Yusuke Nakanishi