你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發綜合 >> iOS-二進制協議的封裝

iOS-二進制協議的封裝

編輯: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

小結:面向對象的思想封裝,使數據實體和對數據實體的操作相關連

 


 

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved