美文网首页
数据交互协议

数据交互协议

作者: xgou | 来源:发表于2016-08-15 18:30 被阅读409次

    数据交互协议

    主要是用于数据封包,拆包的数据协议。

    协议规则:dataType(sizeof(uint8_t))->fileSizeLen(sizeof(NSUInteger))->fileNameLen(sizeof(uint8_t),当是文本和图片以及声音的时候为0,即仅仅是传文件的时候有效)->fileName(自身决定,当是文本和图片以及声音的时候为0,即仅仅是传文件的时候有效)->fileData(自身决定)

    • 数据流按这样的顺序。
    1. packWithDataInfo 用于把我们的数据封装成NSData,然后在转化成流发送出去。

    2. unPackWithData 就用拆封刚才的数据,转成我们需要的可识别的对象。

    Demo:

    一、 封包

    DataInfo *dataInfo = [[DataInfo alloc] init];

    1. 发送文件类
    NSString *filePath = [[NSBundle mainBundle] pathForResource:@"suff" ofType:@"zip"];
    
    dataInfo.dataType = FileDataType;
    
    dataInfo.fileName = @"suff.zip";
    
    dataInfo.fileData = [NSData dataWithContentsOfFile:filePath];
    
    1. 发送文本类
    dataInfo.dataType = TextDataType;
    
    dataInfo.text = textField.text;
    
    
    1. 发送图片和声音是一样的
    dataInfo.dataType = VoiceDataType OR PictureDataType;
    
    dataInfo.fileData = data;
    
    [self.socket sendData:[PeerFileManager packWithDataInfo:dataInfo]];
    

    二、拆包

    NSInteger temp = 0;
    DataInfo *dataInfo = [PeerFileManager unPackWithData:data surplusValue:&temp];
    //ps:如果temp是>=0说明数据包是个完整的,否则说明数据不完整
    switch (dataInfo.dataType) {
    
        case TextDataType:
            
            return dataInfo.text;
        case VoiceDataType:
        
            [dataInfo.fileData writeToFile:[DocumentPath stringByAppendingPathComponent:@"voice.wav"] atomically:YES];
            break;
        case PictureDataType:
        
            [dataInfo.fileData writeToFile:[DocumentPath stringByAppendingPathComponent:@"picture.png"] atomically:YES];
            break;
        case FileDataType:
        
            [dataInfo.fileData writeToFile:[DocumentPath stringByAppendingPathComponent:dataInfo.fileName] atomically:YES];
            break;
        default:
        break;
    
    }
    
    • 数据类型
    typedef NS_ENUM(uint8_t, DataType) {
    
    TextDataType,
    
    PictureDataType,
    
    VoiceDataType,
    
    FileDataType
    
    };
    

    自定义对象

    
    //定义一个中间消息体
    
    @interface DataInfo : NSObject
    
    @property (nonatomic, assign) DataType dataType;
    
    @property (nonatomic, assign) uint8_t fileSize;
    
    @property (nonatomic, copy) NSString *fileName;
    
    @property (nonatomic, copy) NSData *fileData;
    
    @property (nonatomic, copy) NSString *text;
    
    @end
    
    //文件处理类
    @interface PeerFileManager : NSObject
    
    + (NSData *)packWithDataInfo:(DataInfo *)theDataInfo;
    
    + (DataInfo *)unPackWithData:(NSData *)theData surplusValue:(NSInteger *)theValue;
    
    @end
    
    

    实现类

    #import "PeerFileManager.h"
    
    @implementation DataInfo
    
    @synthesize dataType,fileSize,fileName,fileData,text;
    
    @end
    
    // 定义些常量
    
    static const int kDataTypeSize = sizeof(uint8_t);
    
    static const int kFileNameLengthSize = sizeof(uint8_t);
    
    static const int kFileSizeLengthSize = sizeof(NSUInteger);
    
    //dataType->fileSizeLen->fileNameLen->fileName->fileData;
    
    @implementation PeerFileManager
    
    
    //封包操作
    + (NSData *)packWithDataInfo:(DataInfo *)theDataInfo {
    
        NSMutableData *mergeData = [NSMutableData data];
        
        uint8_t dataType = theDataInfo.dataType;
        
        NSUInteger fileSize;
        
        [mergeData appendBytes:&dataType length:kDataTypeSize];
        
        if(theDataInfo.dataType == TextDataType) {
        
            fileSize = [[theDataInfo.text dataUsingEncoding:NSUTF8StringEncoding] length];
            
            [mergeData appendBytes:&fileSize length:kFileSizeLengthSize];
            
            [mergeData appendData:[theDataInfo.text dataUsingEncoding:NSUTF8StringEncoding]];
        
        }
        
        else {
        
            fileSize = theDataInfo.fileData.length;
            
            [mergeData appendBytes:&fileSize length:kFileSizeLengthSize];
            
            if(theDataInfo.dataType == FileDataType) {
            
                NSString *fileName = theDataInfo.fileName;
                
                uint8_t fileNameLength = fileName.length;
                
                [mergeData appendBytes:&fileNameLength length:kFileNameLengthSize];
                
                [mergeData appendData:[fileName dataUsingEncoding:NSUTF8StringEncoding]];
        
            }
        
            [mergeData appendData:theDataInfo.fileData];
        
        }
        
        return mergeData;
    
    }
    
    //拆包操作
    
    + (DataInfo *)unPackWithData:(NSData *)theData surplusValue:(NSInteger *)surplusValue {
        
    //dataType->fileSizeLen->fileNameLen->fileName->fileData;
        DataInfo *dataInfo = [[DataInfo alloc] init];
        NSInteger tempSurplusValue = 0;
        tempSurplusValue = theData.length - kDataTypeSize;
        *surplusValue = tempSurplusValue;
    //    头里数据类型长度和文件长度的数据是否存在
        if(tempSurplusValue < 0) {
            return nil;
        }
        int dataType;
        long fileSizeLen;
    //    得到数据类型
        [theData getBytes:&dataType range:NSMakeRange(0, sizeof(dataType))];
    //      主要是处理不同CPU下数据流大小端的问题。
        BOOL isBigEndian = YES;
        if(dataType > FileDataType) {
            isBigEndian = NO;
        }
        
        dataType = isBigEndian ? dataType : CFSwapInt32BigToHost(dataType);
        dataInfo.dataType = dataType;
        if(dataInfo.dataType == BreathDataType) {
            return dataInfo;
        }
        tempSurplusValue -= kFileSizeLengthSize;
        *surplusValue = tempSurplusValue;
        if(tempSurplusValue < 0) {
            NSLog(@"数据包不完整,发生黏包");
            return nil;
        }
    //    得到可用数据长度
        [theData getBytes:&fileSizeLen range:NSMakeRange(kDataTypeSize, kFileSizeLengthSize)];
        fileSizeLen = isBigEndian ? fileSizeLen : CFSwapInt64BigToHost(fileSizeLen);
        tempSurplusValue -= fileSizeLen;
        *surplusValue = tempSurplusValue;
        if(tempSurplusValue < 0) {
            NSLog(@"实体数据不足,发生黏包");
            return nil;
        }
        if(dataType == TextDataType) {
            dataInfo.text = [[NSString alloc] initWithData:[theData subdataWithRange:NSMakeRange(kDataTypeSize + kFileSizeLengthSize, fileSizeLen)] encoding:NSUTF8StringEncoding];
            return dataInfo;
        }
        NSUInteger headerSize = kDataTypeSize + kFileSizeLengthSize;
        
        NSString *fileName;
        int fileNameLen = 0;
        int fileNameSizeLen = 0;
        if(dataType ==  FileDataType) {
            fileNameSizeLen = kFileNameLengthSize;
            tempSurplusValue -= kFileNameLengthSize;
            *surplusValue = tempSurplusValue;
            if(tempSurplusValue < 0) {
                NSLog(@"数据包里文件长度不够,发生黏包");
                return nil;
            }
    //        得到文件名长度
            [theData getBytes:&fileNameLen range:NSMakeRange(kDataTypeSize + kFileSizeLengthSize, kFileNameLengthSize)];
            fileNameLen = isBigEndian ? fileNameLen : CFSwapInt32BigToHost(fileNameLen);
            tempSurplusValue -= fileNameLen;
            *surplusValue = tempSurplusValue;
            if(tempSurplusValue < 0) {
                NSLog(@"数据包里文件名的数据不完整");
                return nil;
            }
            if(fileNameLen > 0) {
                fileName = [[NSString alloc] initWithData:[theData subdataWithRange:NSMakeRange(headerSize + kFileNameLengthSize, fileNameLen)] encoding:NSUTF8StringEncoding];
            }
        }
        if(tempSurplusValue < 0 ) {
            NSLog(@"文件内容不存在");
            return nil;
        }
        NSData *fileData = [theData subdataWithRange:NSMakeRange(headerSize + fileNameSizeLen + fileNameLen , fileSizeLen)];
        dataInfo.fileName = fileName;
        dataInfo.fileData = fileData;
        dataInfo.fileSize = fileSizeLen;
        return dataInfo;
    }
    
    @end
    
    

    相关文章

      网友评论

          本文标题:数据交互协议

          本文链接:https://www.haomeiwen.com/subject/qvwusttx.html