iOS-二进制协议的封装
iOS-二进制协议的封装
对于在SDK socket通信时会存在二进制协议的通信模式,对于此根据以往的工作内容进行小结:
首先在socket通讯中可以有字符串协议和二进制协议,通过协议来达到通讯的目的。对于字符串协议就是通过字符串来制定通讯的标准模式是“string”-“value”模式,通过XML或者json来达到网络传输,解析封装也是基于XML或者json进行信息提取。
对于二进制协议,在C语言是通过struct对协议进行封装,在iOS中使用的是OC,在OC中你也可以通过C语言对二进制协议进行封装,但是在C语言和OC混合变成就会感觉好不爽。所以今天就通过OC谈一谈二进制协议封装。
首先C语言对协议的封装进行分解,一个Struct结构体无非就是协议值的布局,协议值占的byte数,包的大小,结构体的内存块。通过一一对应关系,我们就可以把结构体映射到OC的类中。下面通过一个简单的协议封装结构题和OC的协议封装来理解:
比如现在有一个协议的C语言结构如下
struct { char one; //字符 unsigned short two; //short类型 unsigned int three; //int类型 char * four; //字符串 }BinaryProtocolStruct;
使用OC面向对象的思想对该协议进行封装
头文件:
@interface BinaryProtocolTest : NSObject -(id)initWithOne:(int)one andTwo:(int)two andThree:(int)three andFour:(NSString *)string; -(id)initWithData:(NSData *)data; -(void)setOne:(int)one; -(void)setTwo:(int)two; -(void)setThree:(int)three; -(void)setFour:(NSString *)four; -(int)getOne; -(int)getTwo; -(int)getThree; -(NSString *)getFour; -(NSMutableData *)getProtocolData; -(int)getProtocolSize; +(int)getProtocolSize; @end
实现文件:
//协议的固定大小 #define ProtocolSize 39 @implementation BinaryProtocolTest{ NSMutableData *_protocolData; //协议的内存块 int _protocolSize; //协议的内存块大小 struct{ unsigned short one_offset:8; unsigned short one_len:8; unsigned short two_offset:8; unsigned short two_len:8; unsigned short three_offset:8; unsigned short three_len:8; unsigned short four_offset:8; unsigned short four_len:8; }_protocolLayout; //协议的内存块布局,主要由offset和size决定 } -(void)initProtocolLayout{ _protocolLayout.one_offset=0; _protocolLayout.one_len = 1; _protocolLayout.two_offset = 1; _protocolLayout.two_len = 2; _protocolLayout.three_offset = 3; _protocolLayout.three_len =4; _protocolLayout.four_offset =7; _protocolLayout.four_len =32; _protocolSize = 39; } /* *该方法的主要作用是当你想使用该协议封装自己的数据时使用 */ -(id)initWithOne:(int)one andTwo:(int)two andThree:(int)three andFour:(NSString *)four{ self = [super init]; if (self) { [self initProtocolLayout]; //先初始化协议的内存布局 _protocolData = [[NSMutableData alloc]init];//初始化协议的内存块 [_protocolData resetBytesInRange:NSMakeRange(0, _protocolSize)];//设定内存块的大小 //one为char类型不需要进行网络主机传输模式转换,把one的值写入到内存块中 unsigned char tempOne = one; [_protocolData replaceBytesInRange:NSMakeRange(_protocolLayout.one_offset, _protocolLayout.one_len) withBytes:&tempOne length:_protocolLayout.one_len]; //two为unsigned short 类型,所以要进行网络主机的传输字节顺序的转换 htons ->short 类型的主机存储->网络的网络存储,并写入内存块 unsigned short tempTwo = two; tempTwo = htons(tempTwo); [_protocolData replaceBytesInRange:NSMakeRange(_protocolLayout.two_offset, _protocolLayout.two_len) withBytes:&tempTwo length:_protocolLayout.two_len]; //three 为int类型 所以要进行网络主机的传输字节顺序的转换 htonl ->short 类型的主机存储->网络的网络存储,并写入内存块 unsigned int tempThree = three; tempThree = htonl(tempThree); [_protocolData replaceBytesInRange:NSMakeRange(_protocolLayout.three_offset, _protocolLayout.three_len) withBytes:&tempThree length:_protocolLayout.three_len]; //four为字符串不需要进行存储转换 NSData *tempFour = [four dataUsingEncoding:NSUTF8StringEncoding]; [_protocolData replaceBytesInRange:NSMakeRange(_protocolLayout.four_offset, _protocolLayout.four_len) withBytes:tempFour.bytes length:_protocolLayout.four_len]; } return self; } -(id)init{ self = [super init]; if (self) { [self initProtocolLayout]; _protocolData = [[NSMutableData alloc] init]; [_protocolData resetBytesInRange:NSMakeRange(0, _protocolSize)]; } return self; } -(id)initWithData:(NSData *)data{ self = [super init]; if (self) { [self initProtocolLayout]; if (data.length!=_protocolSize) { return nil; //参数过滤,如果返回的数据包的大小不对,就返回 } _protocolData = [[NSMutableData alloc] init]; [_protocolData resetBytesInRange:NSMakeRange(0, _protocolSize)]; [_protocolData replaceBytesInRange:NSMakeRange(0, _protocolSize) withBytes:data.bytes length:_protocolSize]; } return self; } //one的设置 char -(void)setOne:(int)one{ if (_protocolData.length !=_protocolSize) { //one为char类型不需要进行网络主机传输模式转换,把one的值写入到内存块中 unsigned char tempOne = one; [_protocolData replaceBytesInRange:NSMakeRange(_protocolLayout.one_offset, _protocolLayout.one_len) withBytes:&tempOne length:_protocolLayout.one_len]; } } //two的设置 unsigned short -(void)setTwo:(int)two{ if (_protocolData.length !=_protocolSize) { //two为unsigned short 类型,所以要进行网络主机的传输字节顺序的转换 htons ->short 类型的主机存储->网络的网络存储,并写入内存块 unsigned short tempTwo = two; tempTwo = htons(tempTwo); [_protocolData replaceBytesInRange:NSMakeRange(_protocolLayout.two_offset, _protocolLayout.two_len) withBytes:&tempTwo length:_protocolLayout.two_len]; } } //three的设置 int -(void)setThree:(int)three{ if (_protocolData.length !=_protocolSize) { //three 为int类型 所以要进行网络主机的传输字节顺序的转换 htonl ->short 类型的主机存储->网络的网络存储,并写入内存块 unsigned int tempThree = three; tempThree = htonl(tempThree); [_protocolData replaceBytesInRange:NSMakeRange(_protocolLayout.three_offset, _protocolLayout.three_len) withBytes:&tempThree length:_protocolLayout.three_len]; } } //four的设置 string -(void)setFour:(NSString *)four{ if (_protocolData.length !=_protocolSize) { //four为字符串不需要进行存储转换 NSData *tempFour = [four dataUsingEncoding:NSUTF8StringEncoding]; [_protocolData replaceBytesInRange:NSMakeRange(_protocolLayout.four_offset, _protocolLayout.four_len) withBytes:tempFour.bytes length:_protocolLayout.four_len]; } } //get one -(int)getOne{ if (_protocolData.length !=_protocolSize) { unsigned char temp; [_protocolData getBytes:&temp range:NSMakeRange(_protocolLayout.one_offset, _protocolLayout.one_len)]; return temp; } return 0; } //get two -(int )getTwo{ if (_protocolData.length !=_protocolSize) { unsigned short temp; [_protocolData getBytes:&temp range:NSMakeRange(_protocolLayout.two_offset, _protocolLayout.two_len)]; //short网络存储转本地存储 return ntohs(temp); } return 0; } //get three -(int)getThree{ if (_protocolData.length !=_protocolSize) { unsigned char temp; [_protocolData getBytes:&temp range:NSMakeRange(_protocolLayout.three_offset, _protocolLayout.three_len)]; //int网络存储转本地存储 return ntohl(temp); } return 0; } //get four -(NSString *)getFour{ if (_protocolData.length !=_protocolSize) { NSData *temp = [_protocolData subdataWithRange:NSMakeRange(_protocolLayout.four_offset, _protocolLayout.four_len)]; NSString *tempStr = [[NSString alloc]initWithUTF8String:temp.bytes]; return tempStr; } return nil; } -(NSMutableData *)getProtocolData{ return _protocolData; } -(int)getProtocolSize{ return _protocolSize; } +(int)getProtocolSize{ return ProtocolSize; } @end
小结:面向对象的思想封装,使数据实体和对数据实体的操作相关连
郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。