ケルベロスさんのプログラミング / けるぷろ

プログラマのけるさんことケルベロスです

CoronaSDKでSocket IO

CoronaSDKでSocket IO

2015-12-08

もともとSocket.IOでチャットアプリを作っていたのですが、iOSAndroidのクライアントは用意されていて簡単にできます
が、CoronaSDKやluaには専用のクライアントフレームワークみたいなのがなかったのでSocket.IOのコードとか読んで実装してみました

※Socket通信などの理解レベルが多少曖昧なので以下の記述で通信できることはできましたが、申し訳ないですがかなり中途半端で危うい情報であるということを念頭に置いてお読みください

SocketIOとは

Socket.IO
リアルタイムウェブアプリケーションフレームワーク
様々なリアルタイムWeb技術をラップしてシンプルなインターフェースでリアルタイムWebを使用できるようにしてくれてるやつです

CoronaSDKのOSSにWebSocketができるものがあったのでWebSocketを使用してSockt.IOに対応しようと思います

WebSocketとは

WebSocket - Wikipedia
コンピュータネットワーク用の通信規格(プロトコル)の1つ
低コストでリアルタイム双方向通信ができるプロトコル

クライアントからハンドシェイクと呼ばれる要求をサーバに送ると、WebSocket専用コネクションを確立してその時点で双方向通信を開始することができます

Home | DMC Documentation
このライブラリを使用して実装していきます

実装

  • ライブラリ組み込み dmccuskey/dmc-websockets

    1. 上記をgithubからダウンロード
    2. coronaのプロジェクトディレクトリ(main.luaとかある場所)に下記を突っ込む
      • dmc_coronaディレクトリ
      • dmc_corona.cfg
      • dmc_corona_boot.lua
    3. 準備完了
  • コネクションの確立

    1. handshake urlを作成してサーバーへリクエスト handshake url example : http://example.com:80/socket.io/1/?t=1234567890112
    2. レスボンスからsidを取り出してwsプロトコルurl作成 example : ws://example.com:80/socket.io/1/websocket/9adubaadfadf09andf0
    3. 上記をwebsocetライブラリにつっこんで通信開始
  • 通信

    1. Messageの処理
      • Messageを受信すると下記のようなStringになっています
    '5::{name:honyarara,args:[{honya:honey}}'

5::という数字はMessage送信という意味なので5::の部分は切り取ってからjsonライブラリでdecodeすることでtableとして扱います
送信をするときにも下記の形式で送信します

  • WebSocketライブラリによるソケット通信の概要のコード例
local WebSockets = require 'dmc_corona.dmc_websockets' -- dmc-websocketsライブラリインポート
local function socket_handler(event)  -- websocketsのイベントを受け取るfunction
    local ev_type = event.type
    if ev_type == ws.ONOPEN then
        print 'WebSocket on open'
    elseif ev_type == ws.ONMESSAGE then
        print 'WebSocket on message'

        local mes = event.message
        local mesType = mes.data:sub(1,1)

        if mesType == '5' then -- got message
            local mes_json_str = mes.data:sub(5) -- 5::の部分の切り取り
            local json_table = json.decode(mes_json_str) -- jsondecodeしてtableとして扱う
            local ev_name = json_table.name or 'unknown' -- event name
            local args = json_table.args[1] or {} -- args
            print ('name : '.. ev_name)
            print ('args : '.. tostring(args))
        end -- mestype == 5

    elseif ev_type == ws.ONCLOSE then
        print 'WebSocket on close'
    elseif ev_type == ws.ONERROR then
        print 'websockets on error' 
    end -- if ev_type 
end -- socket_handler

ws = WebSockets:new{ -- 通信開始
    uri = s_url,
}
ws:addEventListener( ws.EVENT, socket_handler) --  リスナー登録

以上

CoronaSDKでもSocket.IOの通信ができました、わあい

参考

Client handshake returns error message "Transport unknown" · Issue #1577 · socketio/socket.io websocket example doesn't work once uploaded on mobile phone (iPhone6) · Issue #28 · dmccuskey/DMC-Corona-Library