0

I am Working on a Network application ... but before sending it over the network i am testing my packing and unpacking of data ... but i am getting a lot of garbage values

myfield in a ui text field .. my label is a uilabel ... mybutton method is called when a button is pressed

in the rec method the value(garbage) in x varies from -231231223432.... to +3423423423.....

also if i could like to pack a nsstring with this data how will i pack and unpack it

 enum 
{
gkMessageSent,
gkMessageNotsent
};


-(void)rec:(NSData *)data
 {

const char *incomingPacket = (const char *)[data bytes];
char messageType = incomingPacket[0];

switch (messageType)
{


    case gkMessageSent: 
    {  


        float x = *(float *)(incomingPacket + 1 );
        // value of x are not correct here
        NSString *resultString = [[NSString alloc] initWithFormat:@"%f",x];

        mylabel.text= resultString;            

        break;
    }

    case gkMessageNotsent: 
    { 
        mylabel.text=@"2";
        break;
    }  

        default:
        mylabel.text=@"3";
        break;


}



 }


 -(IBAction)mybutton{


   float myvalue=[myfield.text floatValue];

    // i check myvalue here and its fine

NSMutableData *data= [NSMutableData dataWithCapacity:1+sizeof(float)];


int myrand=1+rand()%3;

if(myrand==1)
{
    char messageType = gkMessageSent;  
    [data appendBytes:&messageType length:1];


    [data appendBytes:&myvalue length:sizeof(float)];




}
else {
    char messageType = gkMessageNotsent;
    [data appendBytes:&messageType length:1];
    [data appendBytes:&myvalue length:sizeof(float) ];        


}


[self rec:data];  


 }

After Some Research I found a way to pack an NSString into NSmutabledata but cant figure out the unpacking

-(IBAction)mybutton {






   float myvalue=300;


NSString *resultString = [[NSString alloc] initWithFormat:@"%.2f",myvalue];



NSMutableData *data=nil;

data= [NSMutableData dataWithCapacity:1+([resultString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]) ];


int myrand=1+rand()%3;

if(myrand==1)
{
    char messageType = gkMessageSent;  
    [data appendBytes:&messageType length:1];

    [data appendBytes:[resultString UTF8String] length:[resultString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];           



}
else {
    char messageType = gkMessageNotsent;
    [data appendBytes:&messageType length:1];

    [data appendBytes:[resultString UTF8String] length:[resultString lengthOfBytesUsingEncoding:NSUTF8StringEncoding]];         

    }


[self rec:data];   


}



-(void)rec:(NSData *)data{

const char *incomingPacket = (const char *)[data bytes];
char messageType = incomingPacket[0];

switch (messageType)
{


    case gkMessageSent: 
    {  


       // Have to get the String here

        break;
    }

    case gkMessageNotsent: 
    { 
        mylabel.text=@"2";
        break;
    }  

        default:
        mylabel.text=@"3";
        break;


}



}
Ifti
  • 77
  • 11
  • First thing I could suggest is to remove the `switch` statement. Switches are odd in nature when it comes to variable declaration and assignment, and many scoping errors occur there. – Richard J. Ross III Aug 27 '12 at 18:30
  • 1
    @RichardJ.RossIII -- There's nothing (obviously) wrong with the switch. Variable declarations are only a problem if you don't include them inside `{}` braces inside a single `case`. – Hot Licks Aug 27 '12 at 18:33
  • It would be most helpful if you used NSLog to dump your variables at appropriate points and then showed us what you got. – Hot Licks Aug 27 '12 at 18:36
  • @HotLicks How to I do that ... and at what points – Ifti Aug 27 '12 at 18:55
  • why was i given a negative rating O_0 – Ifti Aug 27 '12 at 19:00
  • Probably for not knowing how to do minimal debugging ... or how to look up "NSLog" on the Apple doc site. – Hot Licks Aug 27 '12 at 19:41

1 Answers1

0

You should never send "raw" data of unknown size over the network. If you were using integers, you could send the data by not sending it raw, but "correcting" its byte order to "network order" then reversing the process on the other side:

uint32t foo = htonl(myLong);

and to reverse that:

uint32t myLong = ntohl(networkData4bytesLong);

Floats and doubles can be coerced into using the above, but (to my knowledge) there is no standard way to do this. For even the following hack to work, float must be 32bit IEEE format types on both sides (probably true now on most systems).

One way is to create a union with a long and a float in it:

struct foo {
  uint32_t lng;
  float flt;
};

You should probably add an assert(sizeof(foo) == 4); on both sides too, just to be sure.

You put the float into a union of this type, then use htonl(foo.lng); to convert, and reverse that on the other side.

Perhaps a more reliable (but more difficult way) is to turn the float into a string, send it, then convert back to a floating point type. That said, the above should work for you with the listed assumptions (IEEE, 32bit type);

EDIT: So if you want to use a string, you can do it by appending a null terminated string to the data you send, use a "pascal" type string where the first byte is the length and a NOT null terminated string follows, or you can allow a fixed amount of space that will at least have one terminating NULL. For brevity, I am going to use the 3rd way but the "pascal" way is probably the best to use when you code it.

So, to be 100% sure we have enought space, we'll allocate 20 bytes for the float (way too much):

char floatStr[20];
sprintf(floatStr, "%f", myFloat);
[myData appendBytes:floatStr length:20];

On the other side:

unsigned char *ptr = ...; // set to the start of the string
sscanf(ptr, "%f", &myFloat);
ptr += 20;
David H
  • 40,852
  • 12
  • 92
  • 138
  • I my self thought it the same way ... Convert e float into an nsstring and then sending it .... Float to nsstring can be don't but can't figure out a way of packing and unpacking it into nsdata.... – Ifti Aug 28 '12 at 07:22
  • I have added some more code to the orignal Post Can U help me figure out the unpacking – Ifti Aug 28 '12 at 09:35