数据交互协议

数据交互协议

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

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

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 158,560评论 4 361
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 67,104评论 1 291
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 108,297评论 0 243
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 43,869评论 0 204
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 52,275评论 3 287
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 40,563评论 1 216
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 31,833评论 2 312
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 30,543评论 0 197
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 34,245评论 1 241
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 30,512评论 2 244
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 32,011评论 1 258
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 28,359评论 2 253
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 33,006评论 3 235
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 26,062评论 0 8
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 26,825评论 0 194
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 35,590评论 2 273
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 35,501评论 2 268

推荐阅读更多精彩内容