数据交互协议

数据交互协议

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

协议规则: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

你可能感兴趣的:(数据交互协议)