簡體   English   中英

禁用Nagle的NSOutputStream算法

[英]Disable Nagle's algorithm for NSOutputStream

我正在使用MPCF創建多人游戲。 您可以使用iPhone在iPad上控制太空飛船。

我在隨機的時間和間隔經歷各種延遲和延遲以及緩沖/暫停,現在進入了Apple Technical Q&A NW26論文,該論文討論了禁用Nagle算法。 我正在嘗試,但是我的程序不斷崩潰,我不明白為什么。 似乎CFWriteStreamCopyProperty總是返回NULL。

- (void)stream:(NSStream *)stream handleEvent:(NSStreamEvent)eventCode
{
    switch (eventCode) {
        case NSStreamEventOpenCompleted:

            // Trying to get a handle to the native socket
            CFSocketNativeHandle rawsock;

            // This always return NULL
            CFDataRef socketData = CFWriteStreamCopyProperty((__bridge CFWriteStreamRef)(stream), kCFStreamPropertySocketNativeHandle); 

            // And this row always crash (coz of socketData being NULL i guess)
            CFDataGetBytes(socketData, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8 *)&rawsock); 
            CFRelease(socketData);

            // Code example from Apple that need a handle to the native socket, that I am trying to get above
            int err; 
            static const int kOne = 1;  
            err = setsockopt(rawsock, IPPROTO_TCP, TCP_NODELAY, &kOne, sizeof(kOne)); 
            if (err < 0) {     
                err = errno; 
            }

            break;

        default:
            break;
    }
}

任何幫助表示贊賞。

您假設streamNSOutputStream ,但也可以傳遞NSInputStream 因此它崩潰在那條線上。

這是可以處理兩種情況並修復崩潰的示例代碼:

- (void)disableNaglesAlgorithmForStream:(NSStream *)stream {

    CFDataRef socketData;

    // Get socket data
    if ([stream isKindOfClass:[NSOutputStream class]]) {
        socketData = CFWriteStreamCopyProperty((__bridge CFWriteStreamRef)((NSOutputStream *)stream), kCFStreamPropertySocketNativeHandle);
    } else if ([stream isKindOfClass:[NSInputStream class]]) {
        socketData = CFReadStreamCopyProperty((__bridge CFReadStreamRef)((NSInputStream *)stream), kCFStreamPropertySocketNativeHandle);
    }

    // get a handle to the native socket
    CFSocketNativeHandle rawsock;

    CFDataGetBytes(socketData, CFRangeMake(0, sizeof(CFSocketNativeHandle)), (UInt8 *)&rawsock);
    CFRelease(socketData);

    // Disable Nagle's algorythm

    // Debug info
    BOOL isInput = [stream isKindOfClass:[NSInputStream class]];
    NSString * streamType = isInput ? @"INPUT" : @"OUTPUT";

    int err;
    static const int kOne = 1;
    err = setsockopt(rawsock, IPPROTO_TCP, TCP_NODELAY, &kOne, sizeof(kOne));
    if (err < 0) {
        err = errno;
        NSLog(@"Could Not Disable Nagle for %@ stream", streamType);
    } else {
        NSLog(@"Nagle Is Disabled for %@ stream", streamType);
    }
}

case NSStreamEventOpenCompleted:case NSStreamEventOpenCompleted:應調用此case NSStreamEventOpenCompleted:

對於任何想知道為什么粘貼粘貼后無法編譯的人:

#import <arpa/inet.h>       // for IPPROTO_TCP
#include <netinet/tcp.h>    // for TCP_NODELAY

但是,它不能解決周期性延遲問題。 我仍在尋找防止這種情況的方法。

我錄制了一個演示該問題的簡單視頻,我相信您也遇到了同樣的問題: https : //www.dropbox.com/s/omdqkbckph4b1y2/Multipeer%20Connectivity.mov?dl=0

編輯:我能夠找到一種方法來解決定期的延遲問題。 導致問題的原因是MCNearbyServiceAdvertiser 您需要停止通告對等方以擺脫滯后:連接成功后, stopAdvertisingPeerMCNearbyServiceAdvertiser實例上調用stopAdvertisingPeer方法。

MCNearbyServiceAdvertiser *nearbyServiceAdvertiser;

- (void)session:(MCSession *)session peer:(MCPeerID *)peerID didChangeState:(MCSessionState)state {

    switch (state) {

        case MCSessionStateConnected: {
            dispatch_async(dispatch_get_main_queue(), ^{
                [self.nearbyServiceAdvertiser stopAdvertisingPeer];
            });
        ...
    }
    ...
}

但是延遲只會在30秒后關閉。 我不知道如何使其立即消失。

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM