为NSOutputStream禁用Nagle的算法 [英] Disable Nagle's algorithm for NSOutputStream

查看:220
本文介绍了为NSOutputStream禁用Nagle的算法的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在使用 MPCF创建多人游戏。您可以使用iPhone控制iPad上的太空飞船。

I am creating a multiplayer game using MPCF. You control a spacehip on the iPad using the iPhone.

我遇到了各种滞后和延迟以及随机时间和间隔的缓冲/暂停,现在已经登陆Apples 技术Q& A NW26 论文,讨论禁用Nagle算法。我尝试了,但我的程序不断崩溃,我不明白为什么。似乎CFWriteStreamCopyProperty总是返回NULL。

I am experiencing various amount of lag and latency and buffering/pauses at random times and intervals and have now landed on Apples Technical Q&A NW26 paper that talks about disabled the Nagle Algorithm. Im trying it out but my program keeps crashing and I dont understand why. It seem to be that CFWriteStreamCopyProperty always return 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;
    }
}

感谢任何帮助。

推荐答案

您假设 NSOutputStream ,但也可以传递 NSInputStream
因此它在该行崩溃。

You assuming that stream is an NSOutputStream, but there could be passed NSInputStream also. So it crashes on that line.

这是一个示例代码,可以处理这两种情况并修复崩溃:

Here is a sample code that can handle both scenarios and fixes a crash:

- (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);
    }
}

这应该在<$ c $中调用c> case NSStreamEventOpenCompleted:

对于想知道为何在复制粘贴时无法编译的人:

For anyone wondering why it does not compile when copy-pasted:

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

但是,它对周期性延迟问题没有帮助。
我还在寻找一种方法来阻止这种情况。

However, it does NOT help with periodical latency issues. I'm still searching for a way to prevent that.

我录制了一个简单的视频来演示这个问题,我相信你遇到了同样的问题:
https://www.dropbox.com/ s / omdqkbckph4b1y2 / Multipeer%20Connectivity.mov?dl = 0

I recorded a simple video that demonstrates the issue and I believe you are experiencing the same one: https://www.dropbox.com/s/omdqkbckph4b1y2/Multipeer%20Connectivity.mov?dl=0

编辑:我找到了修复方法周期性延迟问题。导致问题的是 MCNearbyServiceAdvertiser
您需要停止向同行做广告才能摆脱滞后:
MCNearbyServiceAdvertiser上调用 stopAdvertisingPeer 方法/ code>连接成功后立即实例。

I was able to find a way to fix a periodical latency issues. It is an MCNearbyServiceAdvertiser that causes the issues. You need to stop advertising a peer in order to get rid of lags: call a stopAdvertisingPeer method on your MCNearbyServiceAdvertiser instance right after the connection succeeded.

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秒之后,延迟才会关闭。我不知道如何让它立刻消失。

BUT the delays will turn off only after 30 seconds. I don't know how to make it disappear right away.

这篇关于为NSOutputStream禁用Nagle的算法的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆