I've got an app that receives JSON messages
over TCP
. This works perfectly for smaller messages, however sometimes when the messages are large they get cut off in the middle, and the app is unable to parse them.
My iOS code:
- (void)stream:(NSStream *)theStream handleEvent:(NSStreamEvent)streamEvent {
collectedData = [NSMutableData data];
switch (streamEvent) {
case NSStreamEventOpenCompleted:
NSLog(@"Stream opened");
break;
case NSStreamEventHasBytesAvailable:
if (theStream == inputStream) {
NSData *nl = [@"\n" dataUsingEncoding:NSUTF8StringEncoding];
uint8_t bufferz[1024];
int lenz;
while ([inputStream hasBytesAvailable]) {
lenz = [inputStream read:bufferz maxLength:sizeof(bufferz)];
[collectedData appendBytes: (const void *)bufferz length:lenz];
}
NSRange nlRange =[collectedData rangeOfData:nl options:0 range:NSMakeRange(0, [collectedData length])];
while (nlRange.location != NSNotFound) {
// Extract data from the beginning up to (but not including) the newline character:
NSData *jsonData = [collectedData subdataWithRange:NSMakeRange(0, nlRange.location)];
// Remove data from the beginning up to and including the newline character:
[collectedData replaceBytesInRange:NSMakeRange(0, nlRange.location + nlRange.length) withBytes:NULL length:0];
// Process jsonData ...
NSError *error;
NSMutableDictionary *jsonDict = [NSJSONSerialization JSONObjectWithData:jsonData options:NSJSONReadingMutableContainers error:&error];
// ...
NSString* type = [jsonDict objectForKey:@"type"];
//NSLog(@"NEW NEW NEW --> %@\n", jsonDict);
NSString *outputData = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding];
if(error) {
NSLog(@"THE STRING ------------>>>>> %@\n", outputData);
NSLog(@"PARSE ERROR ------------->>>>> : %@\n", error);
}
//NSLog(@"TYPEN ----------------------------------------------> %@", type);
if([type isEqualToString:@"message"]) {
//NSLog(@"New chat message: %@", output);
[self messageReceived:outputData];
} else if([type isEqualToString:@"offlineMessages"]) {
NSLog(@"New offline messages: %@", outputData);
NSLog(@"NEW OFFLINE MESSAGES!!");
[self offlineMessagesReceived:outputData];
}
// Check for another newline character:
nlRange =[collectedData rangeOfData:nl options:0 range:NSMakeRange(0, [collectedData length])];
}
}
break;
case NSStreamEventErrorOccurred:
[self closeNetworkCommunication];
isConnected = 0;
NSLog(@"STREAM ERROR");
//theStream = nil;
break;
case NSStreamEventEndEncountered:
[self closeNetworkCommunication];
isConnected = 0;
NSLog(@"STREAM END");
//theStream = nil;
break;
}
}
This is an example string that the server is sending the app:
{"id":"1", "type":"offlineMessages", "msg": "{\"agentsArray\":[{\"id\":281102,\"msgFrom\":\"V281570150514504\",\"msgDate\":\"2014-04-10T11:09:49.000Z\",\"msgBody\":\"Pellentesque habitant morbi tristique senectus et netus et malesuada fames ac turpis egestas. Donec odio tellus, dictum eu congue id, malesuada non risus. Mauris dapibus velit massa, non laoreet lectus lacinia nec. Morbi sagittis molestie eros, nec blandit sem accumsan eget. Aliquam eu sem egestas, malesuada urna sit amet, gravida velit. Curabitur auctor sit amet turpis vitae feugiat. Nam id velit viverra eros blandit consectetur vel eu tortor. Nullam at augue eros. Praesent dolor libero, venenatis in adipiscing vitae, dignissim nec nisi. In lobortis sem a neque ultrices, a vestibulum urna ullamcorper. Pellentesque eu suscipit est, quis dignissim orci. Aenean condimentum vitae dolor ac cursus. Aenean eu pulvinar nunc, et mollis erat. Vestibulum commodo malesuada nunc et iaculis. In mattis cursus mi vitae gravida. Etiam et iaculis tellus, non iaculis nulla.\",\"channelID\":\"V281570150514504\",\"recipient\":\"[email protected]\"}]}", "name": "281", "time": "12:09", "channel": "V281570150514504"}\n
Sometimes the app will parse the message like this:
auctor sit amet turpis vitae feugiat. Nam id velit viverra eros blandit consectetur vel eu tortor. Nullam at augue eros. Praesent dolor libero, venenatis in adipiscing vitae, dignissim nec nisi. In lobortis sem a neque ultrices, a vestibulum urna ullamcorper. Pellentesque eu suscipit est, quis dignissim orci. Aenean condimentum vitae dolor ac cursus. Aenean eu pulvinar nunc, et mollis erat. Vestibulum commodo malesuada nunc et iaculis. In mattis cursus mi vitae gravida. Etiam et iaculis tellus, non iaculis nulla.\",\"channelID\":\"V281570150514504\",\"recipient\":\"[email protected]\"}]}", "name": "281", "time": "12:09", "channel": "V281570150514504"}\n
I should add that this does not happend all the time, its around 50% off the times.
Any ideas what I'm doing wrong?
JSONObjectWithStream:options:error:
a try. I've never tested this myself where the input are multiple JSON documents, though. – CouchDeveloper