webネタ

Webエンジニアが業務に関係することをメモしていく

iPhoneアプリでNode.js

iphoneアプリでnode.jsと通信する。
ネイティブアプリでリアルタイムな通信ができるので幅が広がりそう。
環境はMacOSX10で、今回は全部ローカル作業。


f:id:R-H:20110929084724p:image

objective-cでWebSocket通信

iPhoneアプリとnode.jsで双方向通信するのは、もちろんWebSocketで行う。node.jsをインストールしたことある人はわかると思うが、WebSocket通信はsocket.IOモジュールで行っているのでクライアントサイド(objective-c)もsocket.IOにしたい。ライブラリはsokect.IO-objcを使う。

インストール

xcode

socket.IO-objcの依存ライブラリをインポート

  • cocoa-websocket
  • RegexKitLite
  • json-framework
  • ASIHTTPRequest

cocoa-websocket

https://github.com/erichocean/cocoa-websocket
git cloneでダウンロードし、以下をプロジェクトにインポート。
AsyncSocket/
SocketIO.h
SocketIO.m


RegexKitLite

http://regexkit.sourceforge.net/RegexKitLite/
tarでダウンロードし、以下をプロジェクトにインポート。
RegexKitLite.h
RegexKitLite.m
あとFrameworksに以下をインポート
libicucore.dylib


json-framework

https://github.com/stig/json-framework/
git cloneでダウンロードし、以下をプロジェクトにインポート。
Classes/


ASIHTTPRequest

http://allseeing-i.com/ASIHTTPRequest/
git cloneでダウンロードし、以下をプロジェクトにインポート。
ここに詳しい説明がある
http://allseeing-i.com/ASIHTTPRequest/Setup-instructions


socket.IO-objcをインポート

https://github.com/pkyeck/socket.IO-objc
git cloneでダウンロードし、以下をプロジェクトにインポート。
SocketIO.h
SocketIO.m

node.js(サーバー側)

node.jsとsocket.ioモジュールのインストール

nodeのインストールはnvmコマンドで行う。

git clone https://github.com/creationix/nvm.git ~/.nvm
. ~/.nvm/nvm.sh
nvm install v0.4.7
nvm use stable

npm install socket.io

サンプル

説明

iPhone側から接続し、接続完了後にnode.js側へobjcイベント発火。(もちろんこのobjcという名前はてきとうにつけたイベント名)
node.js側でobjcイベント受信したら3秒後にiPhone側へメッセージを送信。

xcode

まずxcodeで空のプロジェクトを作る。
名前はSocketIoSampleとした。


SocketIoSampleViewController.h

SocketIODelegateをデリゲート。

#import 
#import "SocketIO.h"
@interface SocketIoSampleViewController : UIViewController
@end


SocketIoSampleViewController.m

viewDidLoadメソッドに下記を追記。

 - (void)viewDidLoad
{
    [super viewDidLoad];
    
    // WebSocket接続
    SocketIO *socketIO = [[SocketIO alloc] initWithDelegate:self];
    [socketIO connectToHost:@"localhost" onPort:3000];
}

// WebSocket接続完了した場合
 - (void) socketIODidConnect:(SocketIO *)socket
{
    NSLog(@"-- socketIODidConnect()");

    // objcイベント発火。(node.js側でon('objc', function() {...})でキャッチ)
    [socket sendEvent:@"objc" withData:[NSDictionary dictionaryWithObject:@"hoge" forKey:@"Key"]];
    NSLog(@"-- sendEvent()");
}

// node.jsからWebSocketでメッセージが送られてきた場合
 - (void) socketIO:(SocketIO *)socket didReceiveEvent:(SocketIOPacket *)packet
{
    NSLog(@"-- didReceiveMessage() >>> data: %@", packet.data);
}
node.js側

conn-objc.js

var io = require('socket.io').listen(3000);
var timer = require('timers');

// WebSocket接続時
io.sockets.on('connection', function (socket) {
  console.log('CONNECTION ok');

  // iPhoneからのobjcイベント受信時
  socket.on('objc', function (data) {
    console.log('CATCH EVENT ok', data);

    // iPhoneからのメッセージ受信3秒後に、node.js側からメッセージ送信
    timer.setTimeout(function() {
        socket.emit('messages', { echo: 'from node.js!' });
        console.log('SEND MESSAGE ok');
    }, 3000);
  });
});


node.jsを起動

node conn-objc.js

xcodeでビルド

xcode側のログ
SocketIoSample[19935:b303] Opening ws://localhost:3000/socket.io/1/websocket/222774812681844920
SocketIoSample[19935:b303] Connection opened.
SocketIoSample[19935:b303] onData 1::
SocketIoSample[19935:b303] connect
SocketIoSample[19935:b303] onConnect()
SocketIoSample[19935:b303] -- socketIODidConnect()
SocketIoSample[19935:b303] send()
SocketIoSample[19935:b303] send() >>> 5:::{"args":{"Key":"hoge"},"name":"objc"}
SocketIoSample[19935:b303] -- sendEvent()
SocketIoSample[19935:b303] doQueue() >> 0
SocketIoSample[19935:b303] setTimeout()
SocketIoSample[19935:b303] onData 5:::{"name":"messages","args":[{"echo":"from node.js!"}]}
SocketIoSample[19935:b303] setTimeout()
SocketIoSample[19935:b303] event
SocketIoSample[19935:b303] -- didReceiveMessage() >>> data: {"name":"messages","args":[{"echo":"from node.js!"}]}
node.js側のログ
   info  - handshake authorized 222774812681844920
   debug - setting request GET /socket.io/1/websocket/222774812681844920
   debug - set heartbeat interval for client 222774812681844920
   debug - client authorized for 
   debug - websocket writing 1::
CONNECTION ok
   debug - websocket received data packet 5:::{"args":{"Key":"hoge"},"name":"objc"}
CATCH EVENT ok { Key: 'hoge' }
   debug - websocket writing 5:::{"name":"messages","args":[{"echo":"from node.js!"}]}
SEND MESSAGE ok
   debug - emitting heartbeat for client 222774812681844920
   debug - websocket writing 2::
   debug - set heartbeat timeout for client 222774812681844920
   debug - websocket received data packet 2::

特に問題なく通信できた。
これでリアルタイム操作が可能なアプリ作れますね。(・・`。