1

I am working on an app that is using NSOutputStream and NSInputStream to try it out and see what I can make happen. I have modified This tutorial to allow me to use a old computer as a server! What I am having an issue with is i am trying to send a dictionary through a NSOutputStream and then receive it. unfortinily the server seems to be adding a byte of data so I can not successfully unarchive the data. Here is my code....

    //sending the data
     NSMutableDictionary *dic = [[NSMutableDictionary alloc] init];
        [dic setObject:@"hi" forKey:@"hello"];
        [dic setObject:@"whats up" forKey:@"huh"]; 
        NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dic];//data is 365 bytes
        NSLog(@"%@",data);
        [self.outputStream write:data.bytes maxLength:data.length];



    //receiving data from NSInputStream
    case NSStreamEventHasBytesAvailable:
        NSLog(@"has bytes available");
        //_mutData = [NSMutableData new];
        _mutData = [[NSMutableData alloc] init];
        if (theStream == inputStream) {

            uint8_t buffer[1024];
            int len;

            while ([inputStream hasBytesAvailable]) {
                len = [inputStream read:buffer maxLength:sizeof(buffer)];
                if (len > 0) {



                    [_mutData appendBytes:buffer length:len];
                    NSLog(@"Data:  %@",_mutData);
                    NSLog(@"appended bytes");



                }
            }
        }
        break;

    // trying to make the data into the dictionary
    NSDictionary *dic = [NSKeyedUnarchiver unarchiveObjectWithData:_mutData];
        NSLog(@"%@",dic);

Upon trying to unarchiveOjectWithData I get an error message of "* -[NSKeyedUnarchiver initForReadingWithData:]: incomprehensible archive (0x62, 0x70, 0x6c, 0x69, 0x73, 0x74, 0x30, 0x30)".

Upon looking at the data it appears that it is all the same except for the last two values of the data that comes in from the server it adds "0a" to the end of the data.

My question is what is going wrong why is this data being added somewhere in the server? Thanks for any help!

Charlie
  • 222
  • 3
  • 20
  • Wow. That's some low level stuff. Take a careful look at Apple's docs on InputStreams. You might spot something you missed. https://developer.apple.com/library/ios/documentation/Cocoa/Conceptual/Streams/Articles/ReadingInputStreams.html – sangony Mar 02 '14 at 01:29
  • I am not insulting you. If anything I was paying you a compliment. By low level I meant root, as in very complex. Google "low level programming language". – sangony Mar 02 '14 at 04:05
  • well sorry I thought that was meant as an insult which believe it or not has happen to me on this site more than once. Unfortunately I still can not find what I am missing in the docs but I will continue to dig on the internet. – Charlie Mar 02 '14 at 17:26
  • I looked at the tutorial you referenced in your question but it does not appear to send a dictionary as its payload but instead just uses NSString. Have you tried just using NSString and see if it works? – sangony Mar 02 '14 at 17:53
  • yes it does send a string but you send it as data. So i thought that along as i convert what ever it is to data then i should be fine. My server prints out what ever data it gets. and it prints out my keys and values and other stuff. look at the comment below for the data – Charlie Mar 02 '14 at 18:03
  • bplist00!"T$topX$objectsX$versionY$archiver?Troot?? U$null? ZNS.objectsV$classWNS.keys???????ShuhUhelloXwhats upRhi?X$classesZ$classname?_NSMutableDictionary\NSDictionaryXNSObject_NSMutableDictionary??_NSKeyedArchive(25: – Charlie Mar 02 '14 at 18:04
  • I think the reason you are not finding much help on this is because it is "low level". Meaning you have to do A LOT of side work manually. You are pretty much working at the TCP level here. Most people would use "higher level" functions like sending a dictionary via a JSON package where a lot of the work you are forced to do manually with streams is done automatically for you. The only reference I could find for your issue is not a precise answer but might help you. Look here http://stackoverflow.com/questions/11826195/gcdasyncsocket-alters-data-while-transporting-it – sangony Mar 02 '14 at 18:13
  • let us [continue this discussion in chat](http://chat.stackoverflow.com/rooms/48810/discussion-between-charlie-and-sangony) – Charlie Mar 02 '14 at 19:01

1 Answers1

1

While I have no idea what was actually going wrong and how make this work as just sending the data and receiving the data. You need some sort of termination part to make this work so I used two methods of converint NSData to a NSString and then converting a NSString to NSData.

    -(NSData *)interprateHexStringToData:(NSString *)hexString { 

    char const *chars = hexString.UTF8String; 
    NSUInteger charCount = strlen(chars); 
    NSUInteger byteCount = charCount / 2; 
    uint8_t *bytes = malloc(byteCount); 
    for (int i = 0; i < byteCount; ++i) { 
    unsigned int value; 
    sscanf(chars + i * 2, "%2x", &value); 
    bytes[i] = value; 
    } 
    return [NSData dataWithBytesNoCopy:bytes length:byteCount freeWhenDone:YES]; 
    } 

    -(NSString *)makeDataIntoString:(NSData *)data { 

    NSUInteger dataLength = [data length]; 
    NSMutableString *string = [NSMutableString stringWithCapacity:dataLength*2]; 
    const unsigned char *dataBytes = [data bytes]; 
    for (NSInteger idx = 0; idx < dataLength; ++idx) { 
    [string appendFormat:@"%02x", dataBytes[idx]]; 
    } 

    return string; 

    } 

to send my data I switched it up to this.

    NSMutableDictionary *dic = [[NSMutableDictionary alloc] init]; 

    [dic setObject:@"hi" forKey:@"hello"]; 
    [dic setObject:@"whats up" forKey:@"huh"]; 

    NSData *data = [NSKeyedArchiver archivedDataWithRootObject:dic]; 

    NSLog(@"%@",data); 


    NSString *setUpString = [NSString stringWithFormat:@"||||%@",[self                 makeDataIntoString:data]]; 
    NSData *stringData = [setUpString dataUsingEncoding:NSUTF8StringEncoding]; 



    [self.outputStream write:stringData.bytes maxLength:stringData.length]; 

To sort out my data once i got it back from the server i did this.

    NSString *stringData = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding]; 

    NSLog(@"%@",stringData); 

    NSString *changed = [stringData stringByReplacingOccurrencesOfString:@"||||" withString:@""]; 
    NSLog(@"%@",changed); 
    NSData *dataFromTheString = [self interprateHexStringToData:changed]; 
    NSLog(@"%@",dataFromTheString); 
    @try { 
    NSDictionary *dictonary = [NSKeyedUnarchiver unarchiveObjectWithData:dataFromTheString]; 
    NSLog(@"%@",dictonary); 
    } 
    @catch (NSException *exception) { 
    NSLog(@"%@",exception); 
    }

I could not have reached this conclusion without sangony link to this other post GCDAsyncSocket alters data while transporting it Thanks!

Community
  • 1
  • 1
Charlie
  • 222
  • 3
  • 20