I am sending JSON from my server to my cocoa app.
The cocoa app receives data like this:
case NSStreamEventHasBytesAvailable:
NSLog(@"begin");
if (theStream == inputStream) {
int len;
uint8_t buffer[4096];
NSString* incoming_message = @"";
while ([inputStream hasBytesAvailable]) {
len = (int)[inputStream read:buffer maxLength:sizeof(buffer)];
NSLog(@"\nThe length is -- %d\n",len);
if (len > 0) {
NSString *mess = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
if(mess != nil){
incoming_message = [NSString stringWithFormat:@"%@%@",incoming_message,mess];
}
}
}
NSLog(@"%@",incoming_message);
// handle icoming message
[self handleIncomingNotification:incoming_message];
}
NSLog(@"end");
break;
The problem is, is if the data begins to be any larger than something like 500 characters it splits into two (the begin
and end
log are called twice) so handleIncomingNotification:
does not work properly as it is passing half the JSON.
When I log len
I get 1448
a lot and sometimes 1479
and then a one off of 4096
So obviously hasBytesAvailable
is not working like it should.
I have tried changing the buffer but that makes no difference.
Please help me come up with a way to fix this. I am surprised this was not an easy google.
I have ended up doing this:
case NSStreamEventHasBytesAvailable:
NSLog(@"begin");
if (theStream == inputStream) {
int len;
uint8_t buffer[1024];
NSString* incoming_message = @"";
while ([inputStream hasBytesAvailable]) {
len = (int)[inputStream read:buffer maxLength:sizeof(buffer)];
if (len > 0) {
NSString *mess = [[NSString alloc] initWithBytes:buffer length:len encoding:NSASCIIStringEncoding];
incoming_message = [NSString stringWithFormat:@"%@%@",incoming_message,mess];
}
}
[self handleStreamMessage:incoming_message];
}
NSLog(@"end");
break;
handleStreamMessage:
NSString*split_message;
-(void)handleStreamMessage:(NSString*)message{
if(split_message == NULL){
split_message = @"";
}else if([split_message length] > 0){
message = [NSString stringWithFormat:@"%@%@",split_message,message];
}
NSLog(@"message:%@",message);
NSError *error;
NSData* data = [message dataUsingEncoding:NSUTF8StringEncoding];
if ([NSJSONSerialization JSONObjectWithData:data options:kNilOptions error:&error] == nil)
{
// not finished the stream as not given proper json data
split_message = message;
}else{
[self handleIncomingNotification:message];
split_message = @"";
}
}
Which appears to be an awful hack that works.
That is not how NSStream networking streams work. If you send X bytes, the receiver will receive N times some amount, which in total will (eventually) be X. N might be 1, 7, or 42 - depends on multiple things.
What you need to do is parse the JSON as it comes in and determine when you have finished receiving enough that it is meaningful. Check out YAJLParser, i use it to do exactly this with the twitter api. Let me get you a link...
.. my fork is here: https://github.com/xaphod/yajl-objc
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.