区块链技术博客
www.b2bchain.cn

ProtoBuf、JSON和iOS数据传输求职学习资料

本文介绍了ProtoBuf、JSON和iOS数据传输求职学习资料,有助于帮助完成毕业设计以及求职,是一篇很好的资料。

对技术面试,学习经验等有一些体会,在此分享。

本篇文章主要讲PB在iOS客户端的使用和iOS数据传输的一些内容

PB在iOS上的安装使用

安装和简单使用这部分主要参考了这篇文章

首先要安装protoc命令,protoc命令提供了将.proto模型文件转换成java c++ objective-c swift等语言的模型文件,也就是PB的解释器等

从PB的官方版本下载格式为 protoc-xxx-osx-x86_64.zip的文件(我一般选择latest-release)

解压后在./bin目录下看到protoc的二进制文件,将此二进制文件拷贝到/usr/local/bin,由此便protoc命令便安装成功了

然后再安装swift-protobuf命令,这个是因为谷歌的protoc并没有提供.proto文件对.swfit文件的转换能力

$ git clone https://github.com/apple/swift-protobuf.git $ cd swift-protobuf

下面的代码选择切换需要的tag(不切换也没啥问题,我是切成了github上的latest-release)

$ git tag -l $ git checkout tags/1.10.2

然后生成swift-protobuf命令:

$ swift build -c release

然后将生成的./build/release/protoc-gen-swift二进制文件拷贝到/usr/local/bin

现在便可以用命令行来将.proto文件转成objc或swfit文件了:

protoc --objc_out=./folder source.proto protoc --swift_out=. ./source/source.proto

Xcode中使用

objc和swift需要分别导入pod 'Protobuf'pod 'SwiftProtobuf'

然后将上面用protoc命令生成.h/.m.swift文件放入工程中就可以使用了

数据传输原理

字符编码

将数据传输前,先讲一下字符编码,因为传输本质都是传01的二进制数据,需要将01数据转换成对应字符才能进行之后的操作:

这里主要参考了阮一峰的博客

  1. ASCII编码:最早的编码,用一个字节(8bit)来表示128个字符,最高一位没有用到统一是0,比如空格是32(二进制是00100000),大写字母A是65(二进制是01000001)。这128个字符表示英文是足够了,但是表示其他语言就不足够,其他国家就将一个字节的128-255用来表示自己的字符(前128个字符还是ASCII码),但是仍然有两个问题,一是每个国家的字符都不一样,标准不统一;二十像中文这样的字符多达十万,一个字节已远远不够。
  2. UTF-8:基于上面的问题,有人提出了简单粗暴的解决方式,用足够长的字节来表示各个国家的所有字符,这就是Unicode,但Unicode只是给了所有字符的二进制表示,却没有明确怎么存储。所以采用Unicode表示有了多种解决方法,比如UTF-16(两个或四个字节存)、UTF-32(统一四个字节存)等,不过目前互联网通用的是UTF-8(1-4个字节存)的解决方法,所以UTF-8只是Unicode编码的一种解决方案。

对于具体UTF-8怎么存储编码,可以看上面的阮一峰博客

知道了字符编码,便清楚了如何将字符和01二进制互相转化,最简单的数据传输便可以了:服务端根据UTF-8字符集将字符转成01二进制,传输到客户端,客户端根据UTF-8字符将01二进制转成字符

以JSON为例,服务端将JSON数据转成字符串,然后字符串转成二进制串,传输到客户端,客户端将二进制串转成字符串,再使用JSON解释器转成JSON数据

JSON解释器可以参考这篇文章

压缩

实际网络传输不会是按原字符串内容传输,在传输前还会进行一步压缩操作,这样内容长度变短可以节省传输时间,HTTP协议常用压缩方式是GZIP压缩,GZIP一般用作文本压缩,会先用LZ77算法对文本字符串进行首次压缩,然后用哈夫曼编码转换成01二进制存储

GZIP的压缩原理可以参考这篇博客

在请求头中客户端会带一个Accept-Encoding字段,表示客户端支持的压缩方式;在响应头中会带一个Content-Encoding,表示响应体数据用什么方式压缩
ProtoBuf、JSON和iOS数据传输

关于Content-EncodingContent-Type关系:前者的行为是和具体内容或格式无关,只是对内容的压缩,而后者只是表明了内容的原始数据的格式

下面是一段demo

NSString *urlString = @"http://www.cnblogs.com/mddblog/p/5215453.html";     NSURL *url = [NSURL URLWithString:urlString];     NSURLRequest *request = [NSURLRequest requestWithURL:url];      NSURLSession *session = [NSURLSession sharedSession];      NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {          NSLog(@"response:n%@",response);         NSLog(@"data:n%@",data);     }];      [task resume];

控制台打印的结果:

2020-07-30 17:39:42.736215+0800 NetDemo[81497:28465173] response: <NSHTTPURLResponse: 0x600000dac160> { URL: https://www.cnblogs.com/mddblog/p/5215453.html } { Status Code: 200, Headers {     "Content-Encoding" =     (         gzip     );     "Content-Type" =     (         "text/html; charset=utf-8"     );     Date =     (         "Thu, 30 Jul 2020 09:39:42 GMT"     );     "Strict-Transport-Security" =     (         "max-age=2592000; includeSubDomains; preload"     );     Vary =     (         "Accept-Encoding"     ); } } 2020-07-30 17:39:42.736475+0800 NetDemo[81497:28465173] data: {length = 47460, bytes = 0x3c21444f 43545950 45206874 6d6c3e0a ... 3c2f6874 6d6c3e0a }

可以看到返回的NSData就是一串二进制数,字符集是UTF-8,原始数据格式是text/html,内容用gzip压缩

值得注意的是,URLSession放回的NSData二进制串是已经解压过的了,比如上面的压缩方式用的gzip,那么URLSession会用gzip来解压
URLSession在七层模型中处于第五层会话层,解压属于第六层表达层,更多分层参考这篇博客

ProtoBuf和JSON格式同理也是这样,对返回的二进制数据进行格式化解析(反序列化),比如JSON就是将二进制数据转换成JSON的字符串,iOS有自带的NSJSONSerialization进行JSON的序列化和反序列化:

NSString *urlString2 = @"https://jsonplaceholder.typicode.com/todos/1";     NSURL *url = [NSURL URLWithString:urlString2];     NSURLRequest *request = [NSURLRequest requestWithURL:url];      NSURLSession *session = [NSURLSession sharedSession];      NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {          NSLog(@"response:n%@",response);         NSLog(@"data:n%@",data);          id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];         NSLog(@"jsonObject:n%@",jsonObject);     }];      [task resume];

jsonObject便是NSJSONSerialization转换成的NSDictionary类型

本篇文章主要讲PB在iOS客户端的使用和iOS数据传输的一些内容

PB在iOS上的安装使用

安装和简单使用这部分主要参考了这篇文章

首先要安装protoc命令,protoc命令提供了将.proto模型文件转换成java c++ objective-c swift等语言的模型文件,也就是PB的解释器等

从PB的官方版本下载格式为 protoc-xxx-osx-x86_64.zip的文件(我一般选择latest-release)

解压后在./bin目录下看到protoc的二进制文件,将此二进制文件拷贝到/usr/local/bin,由此便protoc命令便安装成功了

然后再安装swift-protobuf命令,这个是因为谷歌的protoc并没有提供.proto文件对.swfit文件的转换能力

$ git clone https://github.com/apple/swift-protobuf.git $ cd swift-protobuf

下面的代码选择切换需要的tag(不切换也没啥问题,我是切成了github上的latest-release)

$ git tag -l $ git checkout tags/1.10.2

然后生成swift-protobuf命令:

$ swift build -c release

然后将生成的./build/release/protoc-gen-swift二进制文件拷贝到/usr/local/bin

现在便可以用命令行来将.proto文件转成objc或swfit文件了:

protoc --objc_out=./folder source.proto protoc --swift_out=. ./source/source.proto

Xcode中使用

objc和swift需要分别导入pod 'Protobuf'pod 'SwiftProtobuf'

然后将上面用protoc命令生成.h/.m.swift文件放入工程中就可以使用了

数据传输原理

字符编码

将数据传输前,先讲一下字符编码,因为传输本质都是传01的二进制数据,需要将01数据转换成对应字符才能进行之后的操作:

这里主要参考了阮一峰的博客

  1. ASCII编码:最早的编码,用一个字节(8bit)来表示128个字符,最高一位没有用到统一是0,比如空格是32(二进制是00100000),大写字母A是65(二进制是01000001)。这128个字符表示英文是足够了,但是表示其他语言就不足够,其他国家就将一个字节的128-255用来表示自己的字符(前128个字符还是ASCII码),但是仍然有两个问题,一是每个国家的字符都不一样,标准不统一;二十像中文这样的字符多达十万,一个字节已远远不够。
  2. UTF-8:基于上面的问题,有人提出了简单粗暴的解决方式,用足够长的字节来表示各个国家的所有字符,这就是Unicode,但Unicode只是给了所有字符的二进制表示,却没有明确怎么存储。所以采用Unicode表示有了多种解决方法,比如UTF-16(两个或四个字节存)、UTF-32(统一四个字节存)等,不过目前互联网通用的是UTF-8(1-4个字节存)的解决方法,所以UTF-8只是Unicode编码的一种解决方案。

对于具体UTF-8怎么存储编码,可以看上面的阮一峰博客

知道了字符编码,便清楚了如何将字符和01二进制互相转化,最简单的数据传输便可以了:服务端根据UTF-8字符集将字符转成01二进制,传输到客户端,客户端根据UTF-8字符将01二进制转成字符

以JSON为例,服务端将JSON数据转成字符串,然后字符串转成二进制串,传输到客户端,客户端将二进制串转成字符串,再使用JSON解释器转成JSON数据

JSON解释器可以参考这篇文章

压缩

实际网络传输不会是按原字符串内容传输,在传输前还会进行一步压缩操作,这样内容长度变短可以节省传输时间,HTTP协议常用压缩方式是GZIP压缩,GZIP一般用作文本压缩,会先用LZ77算法对文本字符串进行首次压缩,然后用哈夫曼编码转换成01二进制存储

GZIP的压缩原理可以参考这篇博客

在请求头中客户端会带一个Accept-Encoding字段,表示客户端支持的压缩方式;在响应头中会带一个Content-Encoding,表示响应体数据用什么方式压缩
ProtoBuf、JSON和iOS数据传输

关于Content-EncodingContent-Type关系:前者的行为是和具体内容或格式无关,只是对内容的压缩,而后者只是表明了内容的原始数据的格式

下面是一段demo

NSString *urlString = @"http://www.cnblogs.com/mddblog/p/5215453.html";     NSURL *url = [NSURL URLWithString:urlString];     NSURLRequest *request = [NSURLRequest requestWithURL:url];      NSURLSession *session = [NSURLSession sharedSession];      NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {          NSLog(@"response:n%@",response);         NSLog(@"data:n%@",data);     }];      [task resume];

控制台打印的结果:

2020-07-30 17:39:42.736215+0800 NetDemo[81497:28465173] response: <NSHTTPURLResponse: 0x600000dac160> { URL: https://www.cnblogs.com/mddblog/p/5215453.html } { Status Code: 200, Headers {     "Content-Encoding" =     (         gzip     );     "Content-Type" =     (         "text/html; charset=utf-8"     );     Date =     (         "Thu, 30 Jul 2020 09:39:42 GMT"     );     "Strict-Transport-Security" =     (         "max-age=2592000; includeSubDomains; preload"     );     Vary =     (         "Accept-Encoding"     ); } } 2020-07-30 17:39:42.736475+0800 NetDemo[81497:28465173] data: {length = 47460, bytes = 0x3c21444f 43545950 45206874 6d6c3e0a ... 3c2f6874 6d6c3e0a }

可以看到返回的NSData就是一串二进制数,字符集是UTF-8,原始数据格式是text/html,内容用gzip压缩

值得注意的是,URLSession放回的NSData二进制串是已经解压过的了,比如上面的压缩方式用的gzip,那么URLSession会用gzip来解压
URLSession在七层模型中处于第五层会话层,解压属于第六层表达层,更多分层参考这篇博客

ProtoBuf和JSON格式同理也是这样,对返回的二进制数据进行格式化解析(反序列化),比如JSON就是将二进制数据转换成JSON的字符串,iOS有自带的NSJSONSerialization进行JSON的序列化和反序列化:

NSString *urlString2 = @"https://jsonplaceholder.typicode.com/todos/1";     NSURL *url = [NSURL URLWithString:urlString2];     NSURLRequest *request = [NSURLRequest requestWithURL:url];      NSURLSession *session = [NSURLSession sharedSession];      NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {          NSLog(@"response:n%@",response);         NSLog(@"data:n%@",data);          id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];         NSLog(@"jsonObject:n%@",jsonObject);     }];      [task resume];

jsonObject便是NSJSONSerialization转换成的NSDictionary类型

本篇文章主要讲PB在iOS客户端的使用和iOS数据传输的一些内容

PB在iOS上的安装使用

安装和简单使用这部分主要参考了这篇文章

首先要安装protoc命令,protoc命令提供了将.proto模型文件转换成java c++ objective-c swift等语言的模型文件,也就是PB的解释器等

从PB的官方版本下载格式为 protoc-xxx-osx-x86_64.zip的文件(我一般选择latest-release)

解压后在./bin目录下看到protoc的二进制文件,将此二进制文件拷贝到/usr/local/bin,由此便protoc命令便安装成功了

然后再安装swift-protobuf命令,这个是因为谷歌的protoc并没有提供.proto文件对.swfit文件的转换能力

$ git clone https://github.com/apple/swift-protobuf.git $ cd swift-protobuf

下面的代码选择切换需要的tag(不切换也没啥问题,我是切成了github上的latest-release)

$ git tag -l $ git checkout tags/1.10.2

然后生成swift-protobuf命令:

$ swift build -c release

然后将生成的./build/release/protoc-gen-swift二进制文件拷贝到/usr/local/bin

现在便可以用命令行来将.proto文件转成objc或swfit文件了:

protoc --objc_out=./folder source.proto protoc --swift_out=. ./source/source.proto

Xcode中使用

objc和swift需要分别导入pod 'Protobuf'pod 'SwiftProtobuf'

然后将上面用protoc命令生成.h/.m.swift文件放入工程中就可以使用了

数据传输原理

字符编码

将数据传输前,先讲一下字符编码,因为传输本质都是传01的二进制数据,需要将01数据转换成对应字符才能进行之后的操作:

这里主要参考了阮一峰的博客

  1. ASCII编码:最早的编码,用一个字节(8bit)来表示128个字符,最高一位没有用到统一是0,比如空格是32(二进制是00100000),大写字母A是65(二进制是01000001)。这128个字符表示英文是足够了,但是表示其他语言就不足够,其他国家就将一个字节的128-255用来表示自己的字符(前128个字符还是ASCII码),但是仍然有两个问题,一是每个国家的字符都不一样,标准不统一;二十像中文这样的字符多达十万,一个字节已远远不够。
  2. UTF-8:基于上面的问题,有人提出了简单粗暴的解决方式,用足够长的字节来表示各个国家的所有字符,这就是Unicode,但Unicode只是给了所有字符的二进制表示,却没有明确怎么存储。所以采用Unicode表示有了多种解决方法,比如UTF-16(两个或四个字节存)、UTF-32(统一四个字节存)等,不过目前互联网通用的是UTF-8(1-4个字节存)的解决方法,所以UTF-8只是Unicode编码的一种解决方案。

对于具体UTF-8怎么存储编码,可以看上面的阮一峰博客

知道了字符编码,便清楚了如何将字符和01二进制互相转化,最简单的数据传输便可以了:服务端根据UTF-8字符集将字符转成01二进制,传输到客户端,客户端根据UTF-8字符将01二进制转成字符

以JSON为例,服务端将JSON数据转成字符串,然后字符串转成二进制串,传输到客户端,客户端将二进制串转成字符串,再使用JSON解释器转成JSON数据

JSON解释器可以参考这篇文章

压缩

实际网络传输不会是按原字符串内容传输,在传输前还会进行一步压缩操作,这样内容长度变短可以节省传输时间,HTTP协议常用压缩方式是GZIP压缩,GZIP一般用作文本压缩,会先用LZ77算法对文本字符串进行首次压缩,然后用哈夫曼编码转换成01二进制存储

GZIP的压缩原理可以参考这篇博客

在请求头中客户端会带一个Accept-Encoding字段,表示客户端支持的压缩方式;在响应头中会带一个Content-Encoding,表示响应体数据用什么方式压缩
ProtoBuf、JSON和iOS数据传输

关于Content-EncodingContent-Type关系:前者的行为是和具体内容或格式无关,只是对内容的压缩,而后者只是表明了内容的原始数据的格式

下面是一段demo

NSString *urlString = @"http://www.cnblogs.com/mddblog/p/5215453.html";     NSURL *url = [NSURL URLWithString:urlString];     NSURLRequest *request = [NSURLRequest requestWithURL:url];      NSURLSession *session = [NSURLSession sharedSession];      NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {          NSLog(@"response:n%@",response);         NSLog(@"data:n%@",data);     }];      [task resume];

控制台打印的结果:

2020-07-30 17:39:42.736215+0800 NetDemo[81497:28465173] response: <NSHTTPURLResponse: 0x600000dac160> { URL: https://www.cnblogs.com/mddblog/p/5215453.html } { Status Code: 200, Headers {     "Content-Encoding" =     (         gzip     );     "Content-Type" =     (         "text/html; charset=utf-8"     );     Date =     (         "Thu, 30 Jul 2020 09:39:42 GMT"     );     "Strict-Transport-Security" =     (         "max-age=2592000; includeSubDomains; preload"     );     Vary =     (         "Accept-Encoding"     ); } } 2020-07-30 17:39:42.736475+0800 NetDemo[81497:28465173] data: {length = 47460, bytes = 0x3c21444f 43545950 45206874 6d6c3e0a ... 3c2f6874 6d6c3e0a }

可以看到返回的NSData就是一串二进制数,字符集是UTF-8,原始数据格式是text/html,内容用gzip压缩

值得注意的是,URLSession放回的NSData二进制串是已经解压过的了,比如上面的压缩方式用的gzip,那么URLSession会用gzip来解压
URLSession在七层模型中处于第五层会话层,解压属于第六层表达层,更多分层参考这篇博客

ProtoBuf和JSON格式同理也是这样,对返回的二进制数据进行格式化解析(反序列化),比如JSON就是将二进制数据转换成JSON的字符串,iOS有自带的NSJSONSerialization进行JSON的序列化和反序列化:

NSString *urlString2 = @"https://jsonplaceholder.typicode.com/todos/1";     NSURL *url = [NSURL URLWithString:urlString2];     NSURLRequest *request = [NSURLRequest requestWithURL:url];      NSURLSession *session = [NSURLSession sharedSession];      NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData * _Nullable data, NSURLResponse * _Nullable response, NSError * _Nullable error) {          NSLog(@"response:n%@",response);         NSLog(@"data:n%@",data);          id jsonObject = [NSJSONSerialization JSONObjectWithData:data options:0 error:nil];         NSLog(@"jsonObject:n%@",jsonObject);     }];      [task resume];

jsonObject便是NSJSONSerialization转换成的NSDictionary类型

部分转自互联网,侵权删除联系

赞(0) 打赏
部分文章转自网络,侵权联系删除b2bchain区块链学习技术社区 » ProtoBuf、JSON和iOS数据传输求职学习资料
分享到: 更多 (0)

评论 抢沙发

  • 昵称 (必填)
  • 邮箱 (必填)
  • 网址

b2b链

联系我们联系我们