计算机中对数据的存储有两种方式:小端存储(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];