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
小結:物件導向的思想封裝,使資料實體和對資料實體的操作相關連