2015-11-13 2 views
7

J'ai un problème avec le développement d'un serveur/client tcp dans l'objectif c avec Bonjour.iOS Le client du serveur tcp NSStream ne peut pas communiquer

Côté serveur, j'ouvre correctement les flux et j'utilise la fonction handleEvent pour envoyer et recevoir des données. Mais je ne sais pas quel est le bon moyen d'envoyer et de recevoir des données. J'ai lu cet excellent message: Correct way to send data through a socket with NSOutputStream J'utiliser un système mis en attente de paquets pour envoyer des données:

switch(eventCode) { 

    case NSStreamEventOpenCompleted: { 
     NSLog(@"Complete"); 

    } break; 

    case NSStreamEventHasSpaceAvailable: { 
     if (stream == _outputStream) 
      [self _sendData]; 
    } break; 

...

- (void)_sendData { 
flag_canSendDirectly = NO; 
NSData *data = [_dataWriteQueue lastObject]; 
if (data == nil) { 
    flag_canSendDirectly = YES; 
    return; 
} 
uint8_t *readBytes = (uint8_t *)[data bytes]; 
readBytes += currentDataOffset; 
NSUInteger dataLength = [data length]; 
NSUInteger lengthOfDataToWrite = (dataLength - currentDataOffset >= 1024) ? 1024 : (dataLength - currentDataOffset); 
NSInteger bytesWritten = [_outputStream write:readBytes maxLength:lengthOfDataToWrite]; 
currentDataOffset += bytesWritten; 
if (bytesWritten > 0) { 
    self.currentDataOffset += bytesWritten; 
    if (self.currentDataOffset == dataLength) { 
     [self.dataWriteQueue removeLastObject]; 
     self.currentDataOffset = 0; 
    } 
} 

}

. Donc, fondamentalement, je viens d'envoyer séparément mes données sur de nombreux paquets. Mais je ne vois pas comment reconstruire les données du côté client. Et je pense que je n'ai pas correctement compris l'événement NSStreamEventHasBytesAvailable. Parce que ici j'envoie beaucoup de paquets mais cet évènement côté client n'est appelé qu'une seule fois. Et quand je reconstitue les données du tampon les données semblent être corrompues. J'apprécierais vraiment si quelqu'un peut clarifier tout cela, la documentation n'est pas vraiment claire sur ce point (ou peut-être que je manque un point ..).

 case NSStreamEventHasBytesAvailable: { 
     if (stream == _inputStream) 
     { 
      //read data 
      uint8_t buffer[1024]; 
      int len; 
      while ([_inputStream hasBytesAvailable]) 
      { 
       len = [_inputStream read:buffer maxLength:sizeof(buffer)]; 
       if (len > 0) 
       { 
        NSString *output = [[NSString alloc] initWithBytes:buffer length:len encoding:NSUTF8StringEncoding]; 
        //NSData *theData = [[NSData alloc] initWithBytes:buffer length:len]; 
        UnitySendMessage("AppleBonjour_UnityNetworkManager(Clone)", "OnLocalClientReceiveMessageFromServer", [output cStringUsingEncoding:NSUTF8StringEncoding]); 
       } 
      } 
     } 
+0

Avez-vous essayé un test simple? Envoyer une seule chaîne courte. Qu'est-ce que vous obtenez dans votre "sortie" variable lorsque vous faites cela? fwiw; il ne doit pas y avoir un seul appel d'octets disponible pour chaque envoi, ils seront combinés s'ils arrivent à temps et une lecture les obtiendra tous. S'il vous plaît essayez ce test et dites-nous ce que vous obtenez. –

+0

Oh, j'ai oublié une chose de plus; vous pouvez tester le récepteur avec un simple programme tcp telnet. Connectez-vous simplement à votre port et tapez du texte. Si le code du récepteur fonctionne, vous devriez obtenir votre texte directement. –

+0

D'accord, une simple chaîne a fonctionné. Donc, si j'envoie une chaîne plus grande que le buffer, je dois juste la reconstruire chaque fois que le NSStreamEventHasBytesAvailable est appelé. Mais comment puis-je avoir une notification lorsque la chaîne a été envoyée complètement? – thegrandwaazoo

Répondre

3

Il semble que vous utilisez deux variables currentDataOffset - une variable d'instance et une propriété - pour le même but. Si vous avez besoin des deux, vous devez également définir 0 sur currentDataOffset. Mais je pense que le fragment devrait ressembler à:

readBytes += currentDataOffset; 
NSUInteger dataLength = [data length]; 
NSUInteger lengthOfDataToWrite = MIN(dataLength - currentDataOffset, 1024); 
NSInteger bytesWritten = [_outputStream write:readBytes maxLength:lengthOfDataToWrite]; 
if (bytesWritten > 0) { 
    currentDataOffset += bytesWritten; 
    if (currentDataOffset == dataLength) { 
     [self.dataWriteQueue removeLastObject]; 
     currentDataOffset = 0; 
    } 
}