美文网首页
数据交互协议

数据交互协议

作者: 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

相关文章

  • 数据交互协议

    数据交互协议 主要是用于数据封包,拆包的数据协议。 协议规则:dataType(sizeof(uint8_t))-...

  • 关于node中数据交互的理解

    什么是数据交互? 数据交互是httpd协议中常见的,数据交互顾名思义就是我把数据传输给你,你再把数据返回给我,这么...

  • Android基础(15)—网络传输协议

    网络传输协议 App与服务器交互就会涉及到信息的交换,而信息的交互就必然需要一套完整的数据协议。网络传输协议或简称...

  • HTTP协议、存储、Ajax

    前后端数据交互与 HTTP 协议 1、前后端通信是什么(1)前端和后端交互的过程(2)浏览器和服务器之间数据交互的...

  • 数据协议

    健康项目硬件交互协议 数据提交接口http://***:8082/app/data/commit。 所有数据都提交...

  • API接口设计规范

    协议 http https(使用HTTPS协议,以确保交互数据的传输安全) 域名 专门的api应用使用独立域名 h...

  • 小程序 类JSONP 用法, 后台控制调用方法

    JSONP: 一种非官方跨域数据交互协议小程序: 不存在跨域问题 解决: 后台动态调用并有数据交互 小程序端: 基...

  • 物联网应用-基于Aspects的AOP实战

    项目背景: 蓝牙或WiFi的项目,通常会按照订制好的协议交互数据。比如从BLE接收到数据:0x01,按照协议解析数...

  • Protobuf协议

    数据交互协议 在网络通信中,我们经常需要通过一种约定俗称的方式来进行数据交互。在这中间,有很多如xml,json等...

  • TCP/IP的工作方式

    本章内容: TCP/IP协议系统 OSI模型 数据包 TCP/IP的交互方式 TCP/IP协议系统 在网上发送和传...

网友评论

      本文标题:数据交互协议

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