Tech Racho エンジニアの「?」を「!」に。
  • 開発

[Objective-C] iPhoneテスト用に超手抜きUDPサーバを作ってみた

先日の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:が呼ばれます。

エラー処理や再送処理はおろか、ポート番号すらべた書きのものですが、重要でないデータを受け取る分には、ちょっと改良すれば使い物になりそうです。


CONTACT

TechRachoでは、パートナーシップをご検討いただける方からの
ご連絡をお待ちしております。ぜひお気軽にご意見・ご相談ください。