5

MPCF을 사용하여 멀티 플레이어 게임을 만들고 있습니다. 당신은 아이폰을 사용하여 iPad에서 우주선을 통제합니다.NSOutputStream에 대한 Nagle 알고리즘 사용 안 함

임의의 시간과 간격으로 다양한 지연 시간과 대기 시간 및 버퍼링/일시 중지가 발생했으며 이제는 Nagle 알고리즘이 비활성화 된 것에 대해 사과 한 Technical Q&A NW26 종이에 도착했습니다. 나는 그것을 시도하지만, 내 프로그램은 계속 충돌하고 왜 이해가 안 돼요. 그것은 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; 
    } 
} 

도움을 주시면 감사하겠습니다.

+0

해결 방법을 찾으셨습니까? 나는 또한 대기 시간을 줄이기 위해 노력하고' 같이 sendData 사용하지 않고 해요 : toPeers : withMode : 오류 :'와'MCSessionSendDataUnreliable' 그래서 난 패킷 손실 처리 방지 할 수 있습니다 ... – jou

+0

아니, 죄송합니다. Bluetooth LE로 전환되었습니다. – bobmoff

+0

너무 나쁨 ... 답변 해 주셔서 감사합니다. 나는 많은 작은 패킷마다 초를 전송하고, 이에 – jou

답변

5

streamNSOutputStream으로 가정하면 NSInputStream도 전달 될 수 있습니다. 그래서 그 라인에서 충돌합니다. 여기

는 두 시나리오를 처리 할 수있는 샘플 코드와 충돌 해결이 복사 - 붙여 넣을 때 컴파일되지 않는 이유 사람이 궁금 들어 case NSStreamEventOpenCompleted:

바로 호출 할 필요가

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

을 :

#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입니다. 당신은 시차를 제거하기 위해 피어 광고를 중지해야합니다 전화 연결이 성공 후 바로 당신의 MCNearbyServiceAdvertiser 인스턴스에서 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초 후 꺼집니다. 나는 그것이 즉시 사라지게하는 방법을 모른다.

+0

멋진 대답, 나는 내 응용 프로그램에서 비슷한 문제가 있었다. 이 대답에 비틀 거리며 내 문제를 해결 한 것 같습니다. – mhorgan