1

グランドセントラルディスパッチをbsdソケットと組み合わせて使用​​して、icmp pingを送信しようとしています。DISPATCH_SOURCE_TYPE_WRITE と DISPATCH_SOURCE_TYPE_READ をディスパッチ ソースとして追加し、非同期で読み書きします。

これは、bsd ソケットを作成してディスパッチ ソースをインストールする方法です。

- (void)start
{
    int                     err;
    const struct sockaddr * addrPtr;

    assert(self.hostAddress != nil);

    // Open the socket.

    addrPtr = (const struct sockaddr *) [self.hostAddress bytes];

    fd = -1;
    err = 0;
    switch (addrPtr->sa_family) {
        case AF_INET: {
            fd = socket(AF_INET, SOCK_DGRAM, IPPROTO_ICMP);
            if (fd < 0) {
                err = errno;
            }
        } break;
        case AF_INET6:
            assert(NO);
            // fall through
        default: {
            err = EPROTONOSUPPORT;
        } break;
    }

    if (err != 0) {
        [self didFailWithError:[NSError errorWithDomain:NSPOSIXErrorDomain code:err userInfo:nil]];
    } else {
        dispatch_source_t writeSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_WRITE, fd, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
        dispatch_source_set_event_handler(writeSource, ^{
            abort(); // testing
            // call call method here to send a ping
        });
        dispatch_resume(writeSource);
        //NSLog(@"testout");

        dispatch_source_t readSource = dispatch_source_create(DISPATCH_SOURCE_TYPE_READ, fd, 0, dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0));
        dispatch_source_set_event_handler(readSource, ^{
            unsigned long bytesAvail = dispatch_source_get_data(readSource);
            NSLog(@"bytes available: %lu", bytesAvail);
        });
        dispatch_resume(readSource);
    }
}

//NSLog(@"testout");? が表示されます。面白いことに、書き込みブロックは //NSLog(@"testout"); の場合にのみ呼び出されます。コメントアウトされていません。これは非常に奇妙です。読み取りコールバックはテストしていません。送信は最初に機能する必要があります。

それで、ここで何が起こっているのですか?

4

2 に答える 2

0

エラーが見つかりました:

新しい SDK では、ディスパッチ ソースは、Objective-C オブジェクトではないにもかかわらず、自動参照カウントの対象となります。

そのため、start メソッドが終了すると、ARC はディスパッチ ソースを破棄し、呼び出されることはありません。

NSLog は、ソースが破棄される前にディスパッチ ソースがトリガーされるように、start メソッドの終了を遅らせます。

于 2013-10-04T20:03:36.040 に答える