2015-11-13 90 views
7

我在使用Bonjour的目標c中開發tcp服務器/客戶端時遇到問題。iOS NSStream tcp服務器客戶端無法通信

在服務器端,我打開正確的流,並使用handleEvent函數發送和接收數據。但我不知道發送和接收數據的正確方式是什麼。我讀了這個優秀的帖子:Correct way to send data through a socket with NSOutputStream 於是我就用一包排隊系統發送數據:

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

}

。所以基本上我只是發送很多數據包的數據。但是我不知道如何在客戶端重新構建數據。我想我沒有正確理解NSStreamEventHasBytesAvailable事件。因爲在這裏我發送了很多數據包,但是客戶端的這個事件只能調用一次。當我從緩衝區重建數據時,數據似乎已損壞。我真的很感激,如果有人能夠澄清這一切,這個文件不是很清楚(或者我可能會錯過一點)。

 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

您是否嘗試過簡單測試?發送一個簡短的字符串。當你這樣做時,你在變量「輸出」中得到什麼? FWIW;每次發送都不需要單個字節的可用字節數,如果他們及時到達,他們將被合併,一次讀取將全部獲得。請嘗試這個測試,並告訴我們你得到了什麼。 –

+0

哦,我忘了一件事;你可以用一個簡單的tcp程序如telnet來測試接收器。只需連接到您的端口並鍵入一些文本。如果接收機代碼正在工作,您應該直接獲取文本。 –

+0

好了一個簡單的字符串工作。所以如果我發送比緩衝區大的字符串,每次調用NSStreamEventHasBytesAvailable時我都必須重構它。但是,如何在字符串完全發送時收到通知? – thegrandwaazoo

回答

3

看來,你用兩個變量currentDataOffset - 一個實例變量和屬性 - 爲了同樣的目的。如果你確實需要兩者,你也應該設置0currentDataOffset。但我認爲片段應該看起來像:

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