2015-11-13 11 views
7

Mam problem z rozwojem serwera/klienta TCP w celu c z Bonjour.Klient serwera tcp NSOS iS NSStream nie może komunikować się

Po stronie serwera poprawnie otwieram strumienie i używam funkcji handleEvent do wysyłania i odbierania danych. Ale nie wiem, jaki jest właściwy sposób wysyłania i odbierania danych. Czytałem ten doskonały wpis: Correct way to send data through a socket with NSOutputStream więc korzystać z systemu pakietów w kolejce do wysyłania danych:

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

}

. Więc po prostu wysyłam oddzielne moje dane na wiele pakietów. Ale nie widzę sposobu, aby zrekonstruować dane po stronie klienta. I myślę, że nie zrozumiałem poprawnie zdarzenia NSStreamEventHasBytesAvailable. Ponieważ tutaj wysyłam wiele pakietów, ale to zdarzenie po stronie klienta to wywołanie tylko raz. A kiedy odtwarzam dane z bufora, dane wydają się być uszkodzone. Byłbym bardzo wdzięczny, gdyby ktoś mógł to wszystko wyjaśnić, dokumentacja nie jest bardzo jasna w tym punkcie (a może brakuje mi punktu ...).

 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

Czy próbowałeś prosty test? Wyślij pojedynczy krótki ciąg. Co otrzymujesz w swoim zmiennym "wyjściu", kiedy to robisz? fwiw; nie musi być pojedynczego wywołania bajtów dostępnych dla każdego wysłania, będą one połączone, jeśli przyjdą w czasie, a jeden odczyt dostanie je wszystkie. Wypróbuj ten test i powiedz nam, co otrzymujesz. –

+0

Och, zapomniałem o jeszcze jednej rzeczy; możesz przetestować odbiornik za pomocą prostego programu tcp, takiego jak telnet. Wystarczy połączyć się z portem i wpisać tekst. Jeśli kod odbiornika działa, powinieneś otrzymać swój tekst bezpośrednio. –

+0

OK działa prosty ciąg. Więc jeśli wysyłam łańcuch większy niż bufor, po prostu muszę go zrekonstruować za każdym razem, gdy wywoływany jest NSStreamEventHasBytesAvailable. Ale w jaki sposób mogę otrzymać powiadomienie, gdy ciąg zostanie wysłany całkowicie? – thegrandwaazoo

Odpowiedz

3

Wydaje się, że używasz dwóch zmiennych currentDataOffset - zmiennej instancji i majątkowe - w tym samym celu. Jeśli rzeczywiście potrzebujesz ich obu, powinieneś również ustawić 0 na currentDataOffset. Ale myślę, że fragment powinien wyglądać następująco:

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; 
    } 
} 
Powiązane problemy