iOS NSStream tcp 服务器客户端无法通信
iOS NSStream tcp server client can't communicate
我在使用 Bonjour objective c 中开发 tcp server/client 时遇到问题。
在服务器端,我正确打开了流,并使用 handleEvent 函数发送和接收数据。但我不知道发送和接收数据的正确方法是什么。我读了这个很棒的 post : 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]);
}
}
}
看来,您使用两个变量 currentDataOffset
—— 一个实例变量和一个 属性 —— 用于相同的目的。如果您确实需要它们,您也应该将 0
设置为 currentDataOffset
。但我认为片段应该是这样的:
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;
}
}
我在使用 Bonjour objective c 中开发 tcp server/client 时遇到问题。
在服务器端,我正确打开了流,并使用 handleEvent 函数发送和接收数据。但我不知道发送和接收数据的正确方法是什么。我读了这个很棒的 post : 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]);
}
}
}
看来,您使用两个变量 currentDataOffset
—— 一个实例变量和一个 属性 —— 用于相同的目的。如果您确实需要它们,您也应该将 0
设置为 currentDataOffset
。但我认为片段应该是这样的:
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;
}
}