先日のiPhone性能検証で作ったソースの一部として、超手抜きUDPサーバのコードを載せておきます。
CFSocketが思ったよりも使いにくいので、BSDソケットほとんど生です・・・
/**
* 手抜きUDPサーバ
*/
#import <netinet/in.h>
#import <Foundation/Foundation.h>
@interface MyUdpConnection : NSObject {
id delegate;
}
- (id)initWithDelegate:(id)_delegate; //receiveData:(NSData*)data を実装すること
- (void)bind;
- (void)bindThread;
@end
/**
* 手抜きUDPサーバ実装部
*/
@implementation MyUdpConnection
// 初期化
- (id)initWithDelegate:(id)_delegate {
delegate = _delegate;
return self;
}
// 受信開始
- (void)bind {
NSThread *th = [[NSThread alloc]initWithTarget:self selector:@selector(bindThread) object:nil];
[th start];
}
// 受信用スレッド
- (void)bindThread {
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];
struct sockaddr_in addr;
memset(&addr, 0, sizeof(addr));
addr.sin_port = htons(5555); //適当なポートで待機
addr.sin_family = AF_INET;
addr.sin_addr.s_addr = htonl(INADDR_ANY);
int sock = socket(AF_INET, SOCK_DGRAM, 0);
bind(sock, (struct sockaddr *)&addr, sizeof(addr));
char buf[100000]; //100KBまで対応
while (1) {
//ここでデータを受信するまでブロックされる
int size = recv(sock, buf, sizeof(buf), 0);
//NSDataに変換し、delegateに通知
NSData *data = [NSData dataWithBytes:buf length:size];
[delegate performSelectorOnMainThread:@selector(receiveData:) withObject:data waitUntilDone:YES];
}
[pool drain];
}
@end
これを使うと、たとえばViewControllerなどで
- (void)receiveData:(NSData *)data;
を実装しておいて、
MyUdpConnection *udp = [[MyUdpConnection alloc]initWithDelegate:self];
[udp bind];
のようにすれば、データを受信したときにreceiveData:
が呼ばれます。
エラー処理や再送処理はおろか、ポート番号すらべた書きのものですが、重要でないデータを受け取る分には、ちょっと改良すれば使い物になりそうです。