Disable Nagle's algorithm for NSOutputStream

℡╲_俬逩灬. 提交于 2019-11-30 20:57:06

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

This should be called right in the 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.

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

EDIT: 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];
            });
        ...
    }
    ...
}

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

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!