仕事やプライベートでもUDP関連のプログラムを書くときにAsyncUdpSocketを使っています。自分でソケット関連のコードを書かなくてよいので圧倒的にラクなのですが、このライブラリはドキュメント類があまり充実しておらず、いつも使うときに調べ直すのが面倒なので、ここに備忘録的にまとめておきます。
AsyncUdpSocketの入手
AsyncUdpSocketはcocoaasyncsocketというプロジェクト名の一部として開発されています。ダウンロード用のファイル等は用意されていないので、sourceページの案内に従ってソースコードごと落としてきます。最近はGoogle Codeもgitに対応したようで、gitレポジトリをcloneするように書いてあります。
git clone https://code.google.com/p/cocoaasyncsocket/
cloneしてできたディレクトリのうち、RunLoopディレクトリにあるAsyncUdpSocket.hとAsyncUdpSocket.mがAsyncUDPSocketの本体です。
インストール
基本的にはAsyncUdpSocket.hとAsyncUdpSocket.mをプロジェクトに追加するだけです。iOSアプリの場合はCFNetwork.frameworkを追加する必要があります。Macアプリの場合は必要ありません。
初期化と解放
通常のオブジェクト同様イニシャライザを使って初期化します。
AsyncUdpSocket* udpSock = [[AsyncUdpSocket alloc] init];
送信専用の場合はinitで初期化するだけでも問題ありませんが、delegateをセットするとパケット受信時や送信に失敗した場合などにイベントを受信することができます。一応AsyncUdpSocketDelegateというプロトコルが用意されていますが、このdelegateは特にAsyncUdpSocketDelegateに準拠していなくても警告はでません。
AsyncUdpSocket* udpSock = [[AsyncUdpSocket alloc] initWithDelegate:self];
必要なくなったタイミングでreleaseを呼んで解放します。また、closeを呼んでソケットを閉じてやります。
[udpSock close]; [udpSock release];
基本的には、UDP送受信を扱う適当なクラスのメンバ変数としてAsyncUdpSocketのインスタンスを一つ用意しておき、それを使い回す形にするのがよいでしょう。インスタンスを複数作ったり、送信の度に作るのはわかりにくくなったり負荷が大きくなるので避けましょう。
データの送信
AsyncUdpSocketはconnectして使う方法とそうでない方法がありますが、とりあえずここではわかりやすいconnectしない使い方について書いています。
UDPパケットを送信するには、sendData:toHost:port:withTimeout:tag:メソッドを使います。
NSString* someString = @"foobar"; [udpSock sendData:[someString dataUsingEncoding:NSASCIIStringEncoding] toHost:@"localhost" port:8000 withTimeout:100 tag:0];
送るデータはNSData型なので、文字列を送りたい場合はdataUsingEncoding等を使って変換する必要があります。
データの受信
受信は送信に比べると若干手間がかかります。
準備と待機
初期化の直後に何番のポートで受信するかをbindToPort:error:を使って設定します。(ここではerror:にnilを入れていますが、通常はエラー処理を書いてください)。bindしたら、receiveWithTimeout:tag:を呼んで受信用に待機させておきます。timeoutは特に指定したくないときは-1を指定できます。
udpSock = [[AsyncUdpSocket alloc] initWithDelegate:self]; [udpSock bindToPort:8001 error:nil]; [udpSock receiveWithTimeout:-1 tag:0];
受信イベント
パケットを受信すると、delegateのonUdpSocket:didReceiveData:withTag:fromHost:port:が呼ばれます。当然ここで受信したデータもNSData型です。文字列として扱いたい場合はここでも変換を行います。
- (BOOL)onUdpSocket:(AsyncUdpSocket *)sock didReceiveData:(NSData *)data withTag:(long)tag fromHost:(NSString *)host port:(UInt16)port { NSLog(@"Received: %@", [[[NSString alloc] initWithData:data encoding:NSASCIIStringEncoding] autorelease]); [udpSock receiveWithTimeout:-1 tag:0]; return YES; }
パケットを処理したら、再びreceiveWithTimeout:tag:を手動で呼んで次に来るパケット用に待機させます。
@mi_tsu_hi_r http://t.co/GrziQJqp ここで紹介されてるのとか、何か使えるライブラリがあるっしょ( ´ ▽ ` )ノ