I have an issue with the development of a tcp server/client in objective c with Bonjour.
On the server side I open correctly the streams and I use the handleEvent function to send and receive data. But I don't know what is the proper way to send and receive data. I read this excellent post : Correct way to send data through a socket with NSOutputStream So I use a packet queued system to send data :
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;
}
}
}
. So basically i just send separate my data on many packets. But I don't see how to reconstruct the data on the client side. And I think i didn't correctly understood the NSStreamEventHasBytesAvailable event. Because here I send many packets but this event on the client side is call only once. And when I reconstruct the data from the buffer the data appears to be corrupted. I would really appreciate if someone can clarify all this, the documentation is not really clear on this point (or maybe I miss a 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]);
}
}
}
It seems, that you use two variables currentDataOffset
-- an instance variable and a property -- for the same purpose. If you indeed need both of them, you should set 0
to currentDataOffset
as well. But I think the fragment should look like:
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;
}
}
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With