TCP传输协议:前2个子节为一个固定的字符,这里以0x809B为例,接着为4个子节(存放content的长度),然后为传输的内容content
以下内容都在Demo中,有兴趣可以下载
一、 拼接方式1---使用Byte数组
这里以传输一张图片为例
1.1前期准备---获取一张图片的大小
NSString *path= [[NSBundle mainBundle] pathForResource:@"ceshi" ofType:@"jpeg"];
NSData* content = [NSData dataWithContentsOfFile:path];
int value = (int)content.length;
1.2 将长度value转换为4个字节
Byte byteData[4] = {};
byteData[0] =(Byte)((value & 0xFF000000)>>24);
byteData[1] =(Byte)((value & 0x00FF0000)>>16);
byteData[2] =(Byte)((value & 0x0000FF00)>>8);
byteData[3] =(Byte)((value & 0x000000FF));
//转换为4个字节
1.3 拼接固定字符并转为NSData
Byte byte[] = {0x80,0x9B,byteData[0],byteData[1],byteData[2],byteData[3]};
NSData *temphead = [[NSData alloc]initWithBytes:byte length:6];
1.4 拼接传输的数据(图片)
//拼接content
NSMutableData *m_data = [[NSMutableData alloc] init];
[m_data appendData:temphead];
[m_data appendData:content];
二、 拼接方式2---使用十六进制转换
2.1前期准备---获取一张图片的大小
NSString *path= [[NSBundle mainBundle] pathForResource:@"ceshi" ofType:@"jpeg"];
NSData* content = [NSData dataWithContentsOfFile:path];
int value = (int)content.length;
2.2 将长度value转换十六进制string
//将长度转为十进制string
NSString* decimalString = [NSString stringWithFormat:@"%d",value];
//将十进制string转为十六进制并保证长度为8
NSString* firstHex = [decimalString decimalToHexWithLength:8];//私有方法(见Demo)
2.3 将十六进拼接固定字符并转为NSData
//将十六进制拼接上809B
NSString* hexString = [NSString stringWithFormat:@"809B%@",firstHex];
//将十六进制转为NSData
NSData* temphead = [hexString convertBytesStringToData];
2.4 拼接传输的数据(图片)
//拼接content
NSMutableData *m_data = [[NSMutableData alloc] init];
[m_data appendData:temphead];
[m_data appendData:content];
三、 解析数据
这里是模拟服务器返回的数据
因为发送给服务器内容的格式根服务器返回的内容的格式相同,所以这里我们直接解析我们发送给服务器的数据就可以
3.1 获取头部数据
NSData *head = [_receiveData subdataWithRange:NSMakeRange(0, 6)];//取得头部数据
NSData *lengthData = [head subdataWithRange:NSMakeRange(2, 4)];//取得长度数据
3.2 将4个字节的数据还原为content的长度
1 将lengthData转为16进制数
NSString* hexString = [lengthData convertDataToHexStr];
2 将16进制数转为10进制
NSInteger length = [[hexString hexToDecimal]integerValue];//得出content长度
3.3 取出content的内容
NSInteger complateDataLength = length + 6;//算出一个包完整的长度(内容长度+头长度)
if (_receiveData.length >= complateDataLength)//如果缓存中数据够一个整包的长度
{
//这个data即为我们传出去的数据
NSData *data = [_receiveData subdataWithRange:NSMakeRange(6, length)];//截取一个包的长度(处理粘包)
//显示到程序上
[self.resultImage setImage:[UIImage imageWithData:data]];
}
四、 进制、Byte、Byte数组、NSData的相互转换(参考Demo)
#import "NSString+SwitchData.h"
@implementation NSString (SwitchData)
/**
带子节的string转为NSData
@return NSData类型
*/
-(NSData*) convertBytesStringToData {
NSMutableData* data = [NSMutableData data];
int idx;
for (idx = 0; idx+2 <= self.length; idx+=2) {
NSRange range = NSMakeRange(idx, 2);
NSString* hexStr = [self substringWithRange:range];
NSScanner* scanner = [NSScanner scannerWithString:hexStr];
unsigned int intValue;
[scanner scanHexInt:&intValue];
[data appendBytes:&intValue length:1];
}
return data;
}
/**
十进制转十六进制
@return 十六进制字符串
*/
- (NSString *)decimalToHex {
long long int tmpid = [self intValue];
NSString *nLetterValue;
NSString *str = @"";
long long int ttmpig;
for (int i = 0; i < 9; i++) {
ttmpig = tmpid % 16;
tmpid = tmpid / 16;
switch (ttmpig) {
case 10:
nLetterValue = @"A";
break;
case 11:
nLetterValue = @"B";
break;
case 12:
nLetterValue = @"C";
break;
case 13:
nLetterValue = @"D";
break;
case 14:
nLetterValue = @"E";
break;
case 15:
nLetterValue = @"F";
break;
default:
nLetterValue = [[NSString alloc]initWithFormat:@"%lli", ttmpig];
}
str = [nLetterValue stringByAppendingString:str];
if (tmpid == 0) {
break;
}
}
return str;
}
/**
十进制转十六进制
length 总长度,不足补0
@return 十六进制字符串
*/
- (NSString *)decimalToHexWithLength:(NSUInteger)length{
NSString* subString = [self decimalToHex];
NSUInteger moreL = length - subString.length;
if (moreL>0) {
for (int i = 0; i<moreL; i++) {
subString = [NSString stringWithFormat:@"0%@",subString];
}
}
return subString;
}
/**
十六进制转十进制
@return 十进制字符串
*/
- (NSString *)hexToDecimal {
return [NSString stringWithFormat:@"%lu",strtoul([self UTF8String],0,16)];
}
/*
二进制转十进制
@return 十进制字符串
*/
- (NSString *)binaryToDecimal {
int ll = 0 ;
int temp = 0 ;
for (int i = 0; i < self.length; i ++) {
temp = [[self substringWithRange:NSMakeRange(i, 1)] intValue];
temp = temp * powf(2, self.length - i - 1);
ll += temp;
}
NSString * result = [NSString stringWithFormat:@"%d",ll];
return result;
}
/**
十进制转二进制
@return 二进制字符串
*/
- (NSString *)decimalToBinary {
NSInteger num = [self integerValue];
NSInteger remainder = 0; //余数
NSInteger divisor = 0; //除数
NSString * prepare = @"";
while (true) {
remainder = num%2;
divisor = num/2;
num = divisor;
prepare = [prepare stringByAppendingFormat:@"%d",(int)remainder];
if (divisor == 0) {
break;
}
}
NSString * result = @"";
for (NSInteger i = prepare.length - 1; i >= 0; i --) {
result = [result stringByAppendingFormat:@"%@",
[prepare substringWithRange:NSMakeRange(i , 1)]];
}
return [NSString stringWithFormat:@"%08d",[result intValue]];
}
@end
@implementation NSData (SwitchData)
/**
NSData 转 十六进制string
@return NSString类型的十六进制string
*/
- (NSString *)convertDataToHexStr{
if (!self || [self length] == 0) {
return @"";
}
NSMutableString *string = [[NSMutableString alloc] initWithCapacity:[self length]];
[self enumerateByteRangesUsingBlock:^(const void *bytes, NSRange byteRange, BOOL *stop) {
unsigned char *dataBytes = (unsigned char*)bytes;
for (NSInteger i = 0; i < byteRange.length; i++) {
NSString *hexStr = [NSString stringWithFormat:@"%x", (dataBytes[i]) & 0xff];
if ([hexStr length] == 2) {
[string appendString:hexStr];
} else {
[string appendFormat:@"0%@", hexStr];
}
}
}];
return string;
}
/**
NSData 转 NSString
@return NSString类型的字符串
*/
- (NSString *)dataToString {
Byte *bytes = (Byte *)[self bytes];
NSMutableString *string = [[NSMutableString alloc] init];
for(int i = 0; i< [self length]; i++) {
if (i == 0) {
[string appendString:[NSString stringWithFormat:@"%hhu",bytes[i]]];
}else {
[string appendString:[NSString stringWithFormat:@",%hhu",bytes[i]]];
}
}
return string;
}
@end
写在最后:
希望这篇文章对您有帮助。当然如果您发现有可以优化的地方,希望您能慷慨的提出来。最后祝您工作愉快!