5

için Nagle'in algoritmasını devre dışı bırakma MPCF kullanarak çok oyunculu bir oyun oluşturuyorum. IPhone'u kullanarak iPad'de bir boşluk ayarını kontrol edersiniz.NSOutputStream

Nadir zamanlarda ve aralıklarla çeşitli gecikme ve gecikme ve arabelleğe alma/duraklama deneyimleri yaşıyorum ve şimdi Nagle Algoritması'nı devre dışı bırakma hakkında konuşan Elmalar Technical Q&A NW26 kağıdına indi. Deniyorum ama programım çöküyor ve nedenini anlamıyorum. CFWriteStreamCopyProperty her zaman NULL döndürüyor gibi görünüyor.

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

Herhangi bir yardım için teşekkür ederiz.

+0

Bunun için bir çözüm buldunuz mu? Ayrıca gecikmeyi azaltmaya çalışıyorum ve ' sendData: toPeers: withMode: error:' 'ile MCSessionSendDataUnreliable' kullanmadan paket kaybı ile uğraşmayı engelleyebilirim… – jou

+0

Nope, sorry. Bluetooth LE'ye geçti. – bobmoff

+0

Çok kötü… Cevabınız için teşekkür ederiz. – jou

cevap

5

stream'un NSOutputStream olduğunu varsayıyorsunuz, ancak NSInputStream da iletilebilir. Yani bu satırda çöküyor. İşte

iki senaryoyu işleyebilir bir örnek kod ve kilitlenme giderir: Bu kopyalanıp yapıştırılan zaman derleme değil neden kimse merak edenler için case NSStreamEventOpenCompleted:

sağ çağrılmalıdır

- (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 

Ancak, periyodik gecikme sorunları ile yardımcı DEĞİLDİR. Bunu önlemek için hala bir yol arıyorum.

Sorunu gösteren basit bir video kaydedilmiş ve senin de aynı birini yaşıyoruz inanıyoruz: https://www.dropbox.com/s/omdqkbckph4b1y2/Multipeer%20Connectivity.mov?dl=0

DÜZENLEME: Ben periyodik gecikme sorunları düzeltmek için bir yol bulmak mümkün oldu. Sorunlara neden olan MCNearbyServiceAdvertiser'dur. Gecikmelerden kurtulmak için bir eş reklam vermeyi durdurmanız gerekir: ,yöntemini, bağlantı başarılı olduktan hemen sonra MCNearbyServiceAdvertiser örneğinizde çağırın.

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

AMA gecikmeler yalnızca 30 saniye sonra kapanacaktır. Bunu nasıl yapacağımı bilmiyorum hemen.

+0

Harika bir cevap, Uygulamamda benzer bir sorun yaşadım ve her saniyede bir çok küçük paket gönderiyordum. Bu cevaba tökezledi ve benim sorunumu çözmüş görünüyor. – mhorgan