LoginSignup
3
3

More than 5 years have passed since last update.

Ruby初心者がWebSocket 02.まずはお試し

Last updated at Posted at 2016-03-03

前回はRubyを入れてWebSocketの環境を作るまででした。

今回は簡単な実装テストもかねてデモを作ります。

サーバ側はem-websocketで検索して教えてくれたGoogle先生のサイトを参考にサンプルを生成。
参考までにGitにあるem-websoketも書いておきます。

require 'em-websocket'
require 'pp'

connnections = []

EM::WebSocket.start({:host => "0.0.0.0", :port => 8888}) do |ws_conn|
    ws_conn.onopen do
        connnections << ws_conn
    end

    ws_conn.onmessage do |message|
        pp message
        connnections.each{|conn| conn.send(message) }
    end
end

これを実行します。

ruby websocket.rb

ClientはJQueryで簡単に書けるということでコレもサンプルをコピらせてもらいました。
単純にチャットするコードです。

<html>
<head><meta charset="UTF-8" />
<title>websocket ruby test</title>
<script type="text/javascript" src="http://code.jquery.com/jquery-2.1.3.min.js"></script>
<script type="text/javascript">
$(function(){
    var ws = new WebSocket('ws://10.32.14.18:8888/');
    $("#send").on('click', function(){
        ws.send($('#message').val());
    });

    ws.onmessage = function(event){
        var message_li = $('<li>').text(event.data);
        $("#msg-area").append(message_li);
    };
});
</script>
</head>
<body>
<input type="text" id="message" />
<input type="button" id="send" value="send"/>
<ul id="msg-area" />
</body>
</html>

んで、起動。
サーバにあげなくとも、普通に.htmlで保存してダブルクリックしてブラウザで開けば動きます。
2つhtml立ち上げて、片方で打てばもう片方に届いていることが確認できます。

↓こんな感じ

websocket_01.jpg

あとは、現在接続している人数や、新しい人が入ってきたら通知したい。あるいは人数を更新したい。と普通に思うので接続数を取れるか試してみる。

さあ、ここからが試行錯誤の開始です。
まずは、新規でコネクションが張られたら今部屋に何人いるかを新規接続者に返してみます。
またついでに既存の接続者には新規接続を通知して、接続者数を通知してみます。
Client側は特に何も弄らなくとも問題なし。

require 'em-websocket'
require 'pp'

connnections = []

EM::WebSocket.start({:host => "0.0.0.0", :port => 8888}) do |ws_conn|
    ws_conn.onopen do
        connnections.each{|conn| conn.send("Connect New Client : #{connnections.length+1}") }   //既存の接続者に通知
        connnections << ws_conn
        ws_conn.send "Welcome! Now Reader is #{connnections.length}"   //新規の接続者に通知
    end

    ws_conn.onclose do
        connnections.each{|conn| conn.send("Reconnect Client : #{connnections.length}") } //既存の接続者に通知
    end

    ws_conn.onmessage do |message|
        pp message
        connnections.each{|conn| conn.send(message) }
    end
end

まずは、最初に接続

websocket02_01.jpg

クライアント側には接続メッセージとともに現在の接続者数が表示されます。
当然、まだ一人なので1です。

次にもう一つブラウザを立ち上げてクライアント起動

websocket02_02.jpg

クライアントには接続者数が2でメッセージが表示されます。
一方で、最初に立ち上げたほうには

websocket02_03.jpg

新しいクライアントが来たことを通知するメッセージと現在の数が出ました。
では、2つ目のブラウザを閉じてみましょう。ws_conn.oncloseがcallされるはずです。

websocket02_04.jpg

Callされたのが確認できます。
ただし、数が合わないです。1でないとおかしい。
コレはソース見れば一目瞭然なのですが、collectionのサイズを単純にlengthしているからで。
collectionの中身を見てconnectionの状況を見ないといけない。
正直、この方法が正しいのかは分からないけど、まずは分かりやすいので試してみます。

ということで、テスト

まずはoncloseの処理でconnectionがどういう状況になるのかを確認する必要がある。
nullになるのかならないのか。
なんか違う状況になるのか。

コレを見ると、どうやらstateというのがあるらしい。これを取得して表示してみる。
とりあえずは、onopenに直書きで。


require 'em-websocket'
require 'pp'

connnections = []

EM::WebSocket.start({:host => "0.0.0.0", :port => 8888}) do |ws_conn|
    ws_conn.onopen do
        i=0
        connnections.each {|conn|
                i=i+1
                pp "Index : #{i} state ? #{conn.state}"  #ここに書いてみる。
        }
        connnections.each{|conn| conn.send("Connect New Client : #{i+1}") }
        connnections << ws_conn
        ws_conn.send "Welcome! Now Reader is #{connnections.length}"
    end

    ws_conn.onclose do
        i=0
        connnections.each {|conn|
                if !conn.nil? then
                        i=i+1
                end
        }
        connnections.each{|conn| conn.send("Reconnect Client : #{i}") }
    end

    ws_conn.onmessage do |message|
        pp message
        connnections.each{|conn| conn.send(message) }
    end
end

で結果。
テストとしては4つのブラウザで接続して、3つ目を閉じて5つめを開いて接続した。

"Index : 1 state ? connected"
"Index : 1 state ? connected"
"Index : 2 state ? connected"
"Index : 1 state ? connected"
"Index : 2 state ? connected"
"Index : 3 state ? connected"
"Index : 1 state ? connected"
"Index : 2 state ? connected"
"Index : 3 state ? closed"
"Index : 4 state ? connected"

どうやら、この方法だと、connectionはnullにならずにcloseした状態のものをずっと保持しているらしい。
毎回ループさせるこの方法がいいのかどうかハナハナ疑問だけど、サンプルプログラムを弄っている状態では
とりあえずコレで何とかなりそうだ。

次はもう少しいい方法がないかを調べてみたい。

3
3
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
3
3