首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >禁用NSOutputStream的Nagle算法

禁用NSOutputStream的Nagle算法
EN

Stack Overflow用户
提问于 2014-05-22 14:56:14
回答 1查看 1.4K关注 0票数 5

我正在创建一个多人游戏使用MPCF。您可以使用iPad来控制iPhone上的空间。

我正经历着各种各样的延迟和延迟,以及随机时间和间隔的缓冲/暂停,现在我已经登陆了Apples 技术问答NW26论文,其中谈到了禁用Nagle算法。我正在尝试,但我的程序不断崩溃,我不明白为什么。CFWriteStreamCopyProperty似乎总是返回NULL。

代码语言:javascript
复制
- (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;
    }
}

任何帮助都是非常感谢的。

EN

回答 1

Stack Overflow用户

发布于 2014-12-09 12:58:43

假设streamNSOutputStream,但也可以传递NSInputStream。所以它在那条线上坠毁了。

下面是一个可以处理两种场景并修复崩溃的示例代码:

代码语言:javascript
复制
- (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:中直接调用。

对于任何想知道为什么在复制粘贴时它不编译的人:

代码语言:javascript
复制
#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

编辑:I能够找到解决周期性延迟问题的方法。引起这些问题的是MCNearbyServiceAdvertiser。为了摆脱延迟,您需要停止对对等方进行广告宣传:在连接成功后立即在您的MCNearbyServiceAdvertiser实例上调用一个MCNearbyServiceAdvertiser方法。

代码语言:javascript
复制
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秒之后,延迟才会关闭。我不知道怎么让它立刻消失。

票数 5
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/23810373

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档