0

我正在开发一个网络应用程序......但在通过网络发送它之前,我正在测试我的数据打包和解包......但我得到了很多垃圾值

ui 文本字段中的 myfield .. 我的标签是 uilabel ... mybutton 方法在按下按钮时被调用

在 rec 方法中,x 中的值(垃圾)从 -231231223432.... 到 +3423423423....

另外,如果我想用这些数据打包一个 nsstring,我将如何打包和解包它

 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];  


 }

经过一些研究,我找到了一种将 NSString 打包到 NSmutabledata 中的方法,但无法弄清楚解包

-(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;


}



}
4

1 回答 1

0

您永远不应该通过网络发送未知大小的“原始”数据。如果您使用的是整数,则可以通过不发送原始数据来发送数据,而是将其字节顺序“纠正”为“网络顺序”,然后在另一端反转该过程:

uint32t foo = htonl(myLong);

并扭转这一点:

uint32t myLong = ntohl(networkData4bytesLong);

可以强制浮动和双打使用上述内容,但是(据我所知)没有标准的方法可以做到这一点。即使是下面的 hack 工作,float 必须是两边的 32 位 IEEE 格式类型(现在在大多数系统上可能都是如此)。

一种方法是创建一个带有 long 和 float 的联合:

struct foo {
  uint32_t lng;
  float flt;
};

您可能应该添加一个 assert(sizeof(foo) == 4); 双方也一样,只是为了确定。

您将浮点数放入这种类型的联合中,然后使用 htonl(foo.lng); 转换,并在另一侧反转。

也许更可靠(但更困难的方法)是将浮点数转换为字符串,发送它,然后转换回浮点类型。也就是说,上述假设适用于您列出的假设(IEEE,32 位类型);

编辑:所以如果你想使用一个字符串,你可以通过将一个空终止的字符串附加到你发送的数据来做到这一点,使用一个“pascal”类型的字符串,其中第一个字节是长度,后面是一个非空终止的字符串,或者您可以允许至少有一个终止 NULL 的固定数量的空间。为简洁起见,我将使用第三种方式,但“pascal”方式可能是您编写代码时最好使用的方式。

因此,为了 100% 确定我们有足够的空间,我们将为浮点分配 20 个字节(太多了):

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

另一方面:

unsigned char *ptr = ...; // set to the start of the string
sscanf(ptr, "%f", &myFloat);
ptr += 20;
于 2012-08-27T21:53:36.283 回答