计算机中对数据的存储有两种方式:小端存储(Little-Endian)就是低位字节排放在内存的低地址端即该值的起始地址,高位字节排放在内存的高地址端。大端存储(Big-Endian)就是高位字节排放在内存的低地址端即该值的起始地址,低位字节排放在内存的高地址端。
讲到小端存储和大端存储就不得不说两个概念:主机字节序和网络字节序.网络传输的数据一般是字节流,而且是大端存储的形式,而自己机器采用的存储方式因操作系统不同而不同,可能是小端存储或者是大端存储.
在iOS中二进制数据都是以NSData的形式存在的,所以在socket编程中只需要把相应的数据类型转换成NSData即可.
1.把Byte类型的数字转换成NSData类型:
NSUInteger type = 5; Byte msgType[] = { type }; NSData *data2 = [NSData dataWithBytes:&msgType length:sizeof(msgType)];
上面是把一个Byte类型值为5的数字转换成NSData类型,因为Byte只有一个字节所以不需要转变字节序
2.把整型数字转变成NSData类型:
NSUInteger len = 5; //由于NSUInteger长度大于一个字节,所以需要把主机字节序转换成网络字节序,htons()为系统自带的函数 short totalLen = htons(len); NSData *data1 = [NSData dataWithBytes: &totalLen length: sizeof(totalLen)];
3.对于NSDictionary和NSArray类型的数据转换成NSData:
首先我们需要把NSDictionary对象或者NSArray对象转换成json字符串,然后再把json字符串转换成NSData:
NSDictionary *dic = @{@"key" : @"value"}; NSString *jsonString = nil; NSError *error; NSData *jsonData = [NSJSONSerialization dataWithJSONObject:dic options:0 // Pass 0 if you don't care about the readability of the generated string error:&error]; if (!jsonData){ NSLog(@"Got an error: %@", error); }else{ jsonString = [[NSString alloc] initWithData:jsonData encoding:NSUTF8StringEncoding]; NSData *msgData = [msgStr dataUsingEncoding:NSUTF8StringEncoding]; }
如果是数组的话需要把相应的dic换成相应的数组对象即可.
举个例子,socket开发中协议定义为:头(2个字节表示总长度+1个字节长度表示类型+消息体),编码如下:
NSMutableData *cmdData = [NSMutableData data]; NSData *msgData; //把业务数据(NSDictionary,NSArray)转换成属性字符串,方法同上 NSString *msgStr = [ELIMUtils dataTOjsonString:msgDic]; msgData = [msgStr dataUsingEncoding:NSUTF8StringEncoding]; //计算包的总长度 short totalLen = (short int)[msgData length]; //2个字节表示总长度,1个字节表示数据类型 totalLen = htons(totalLen + 2 + 1); NSData *data1 = [NSData dataWithBytes: &totalLen length: sizeof(totalLen)]; //1个字节表示消息的类型 Byte msgType[] = { type }; NSData *data2 = [NSData dataWithBytes:&msgType length:sizeof(msgType)]; [cmdData appendData:data1]; [cmdData appendData:data2]; [cmdData appendData:msgData];
