5

Tôi đang tạo trò chơi nhiều người chơi bằng cách sử dụng MPCF. Bạn kiểm soát một không gian trên iPad bằng cách sử dụng iPhone.Tắt thuật toán của Nagle cho NSOutputStream

Tôi đang trải qua nhiều độ trễ và độ trễ khác nhau và đệm/tạm dừng vào các khoảng thời gian và khoảng thời gian ngẫu nhiên và hiện đã hạ cánh trên giấy Táo Technical Q&A NW26 nói về việc tắt thuật toán Nagle. Tôi đang thử nó nhưng chương trình của tôi vẫn bị treo và tôi không hiểu tại sao. Dường như CFWriteStreamCopyProperty luôn trả về 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; 
    } 
} 

Mọi trợ giúp đều được đánh giá cao.

+0

Bạn đã bao giờ tìm được giải pháp cho điều này chưa? Tôi cũng đang cố gắng giảm độ trễ và không sử dụng ' sendData: toPeers: withMode: error: 'với' MCSessionSendDataUnreliable' vì vậy tôi có thể tránh xử lý việc mất gói tin ... – jou

+0

Không, xin lỗi. Đã chuyển sang Bluetooth LE. – bobmoff

+0

Quá tệ ... Cảm ơn bạn đã trả lời. – jou

Trả lời

5

Bạn giả định rằng streamNSOutputStream, nhưng cũng có thể được thông qua NSInputStream. Vì vậy, nó bị treo trên dòng đó.

Dưới đây là một mẫu mã có thể xử lý cả hai kịch bản và sửa chữa một vụ tai nạn:

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

này nên được gọi là ngay trong case NSStreamEventOpenCompleted:

Đối với bất cứ ai tự hỏi tại sao nó không biên dịch khi sao chép dán :

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

Tuy nhiên, nó KHÔNG giúp với các vấn đề về độ trễ định kỳ. Tôi vẫn đang tìm cách ngăn chặn điều đó.

tôi ghi lại một đoạn video đơn giản thể hiện vấn đề này và tôi tin rằng bạn đang trải qua cùng một: https://www.dropbox.com/s/omdqkbckph4b1y2/Multipeer%20Connectivity.mov?dl=0

EDIT: tôi đã có thể tìm thấy một cách để sửa chữa một vấn đề độ trễ định kỳ. Đây là một số MCNearbyServiceAdvertiser gây ra sự cố. Bạn cần ngừng quảng cáo một đồng đẳng để loại bỏ độ trễ: gọi phương thức stopAdvertisingPeer trên phiên bản MCNearbyServiceAdvertiser ngay sau khi kết nối thành công.

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

NHƯNG sự chậm trễ sẽ tắt chỉ sau 30 giây . Tôi không biết làm thế nào để nó biến mất ngay lập tức.

+0

Câu trả lời tuyệt vời, tôi đã gặp phải một vấn đề tương tự trong ứng dụng của tôi, theo đó tôi đã gửi nhiều gói nhỏ mỗi giây. Stumbled khi câu trả lời này và nó dường như đã cố định vấn đề của tôi. – mhorgan