今流行(?)のWebSocketちゃんですが、Objective-Cで触るための日本語のサイトがあまりなかったので。
手順としては、node.js でWebSocket のサーバーを作り(not Socket.IO)、SocketRocketを使ってそのサーバーに接続します。
node.js、Objective-Cともに触ったことがある人を対象にした記事です。
WebSocketサーバーを作る
Socket.IOというのがありますが、今回は使いません。というのも、Socket.IOは「ソケット通信っぽいことをするためのライブラリ」で、WebSocketで繋げないブラウザにはLong Pollingやらでソケット通信風のことをするよう、ラッピングしています。そのため、今回のようにWebSocketだけで接続する場合には適していません、というかSocketRocketが対応していません。
さて、WebSocketのライブラリとしてws: a node.js websocket implementationを使います。
nodeのプロジェクト用ディレクトリ内で、いつもどおりにwsをnpmでインストールし、
npm install ws
サーバー用のapp.jsを以下のような感じで作成します。
var WebSocketServer = require('ws').Server , wss = new WebSocketServer({port: 8080}); wss.on('connection', function(ws) { ws.on('message', function(message) { console.log('received: %s', message); }); ws.send('something'); });
これで、ws://localhost:8080/にWebSocketサーバーを立ち上げることができます。
ws.on('message')でメッセージをクライアント(Obj-C)側から受信し、
ws.sendでメッセージをクライアント側に送信することができます。
さて、app.jsを作成したので、例によって例のごとく
node app.js
でサーバーを起動しておきます。
SocketRocketでサーバーにつなぐ
さて、サーバーは完成したので、SocketRocketを使ってWebSocketサーバーにつなぎます。
SocketRocketは、Square(スクエニじゃない方)が開発しているObjective-C用WebSocketのライブラリです。
インストール
https://github.com/square/SocketRocketから、SocketRocketをダウンロードします。(gitがわからない人はhttps://github.com/square/SocketRocket/zipball/masterから)
その中の「SocketRocket」というフォルダが、ライブラリとして使用するフォルダですので、これをXcodeのプロジェクトに追加してあげることで、使用することができます。
ただし、このライブラリは、以下のフレームワークに依存します。
- libicucore.dylib
- CFNetwork.framework
- Security.framework
- Foundation.framework
なので、これらのフレームワークを追加します。
コード上での使用方法
#import "SRWebSocket.h"
すると、そのソースコード内で、WebSocketを使うことができます。
以下のようにしてSRWebSocketのインスタンスを生成します(Obj-Cおなじみな書き方)。
ここで、つなぐ先は、ws://で始まることに留意して下さい。
SRWebSocket *web_socket = [[SRWebSocket alloc] initWithURLRequest:[NSURLRequest requestWithURL:[NSURL URLWithString:@"ws://localhost:8080/"]]];
delegateを使うので、delegateを設定します。
[web_socket setDelegate:self];
インスタンスを作っただけではつながないので、openメソッドで接続します(ちなみに、閉じるときはclose)。
[web_socket open];
Delgateは、以下の4つが使えます。
上から、「メッセージをサーバーから受信したとき」「接続したとき」「接続に失敗したとき」「接続を終了したとき」に呼ばれます。
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message; - (void)webSocketDidOpen:(SRWebSocket *)webSocket; - (void)webSocket:(SRWebSocket *)webSocket didFailWithError:(NSError *)error; - (void)webSocket:(SRWebSocket *)webSocket didCloseWithCode:(NSInteger)code reason:(NSString *)reason wasClean:(BOOL)wasClean;
「接続したら、サーバー側にメッセージを送信する」を実装してみます。
- (void)webSocketDidOpen:(SRWebSocket *)webSocket{ [webSocket send:@"Nexus 7を発送しました"]; }
すると、node.js上に「received: Nexus 7を発送しました」と表示されます。
sendメソッドで、サーバー側にメッセージを送信できます。※sendメソッドは、文字列だけでなく、Dataも送信できます。
Nexus7は10/1に届くらしいです。
次に「サーバーからメッセージを受信したら、NSLogで表示する」を実装してみます。
- (void)webSocket:(SRWebSocket *)webSocket didReceiveMessage:(id)message{ NSLog(@"%@", [message description]); }
すると、「2012-09-29 13:31:35.896 ProjectName[32523:11303] 目にうつる全てのもの」という感じにNSLogされてるのがわかります。
messageに受信したものが入ってくるので、descriptionメソッドを呼び出してNSLogで出力するなり、JSON用ライブラリに引き渡すなり、なんでもすればいいと思います。
サンプル
僕のサンプルではないですが、SocketRocketに、サンプルが置いてありますので、参考にしてみて下さい。
SocketRocket/TestChat/TCViewController.m at master · square/SocketRocket · GitHub