简介
Thrift是一种接口描述语言和二进制通讯协议,它被用来定义和创建跨语言的服务。它被当作一个远程过程调用(RPC)框架来使用,是由Facebook为“大规模跨语言服务开发”而开发的。(百度百科)
结构 (下面的协议,我们对接过程中会逐渐眼熟)
Thrift支持众多通讯协议:
TBinaryProtocol –一种简单的二进制格式,简单,但没有为空间效率而优化。比文本协议处理起来更快,但更难于调试。
TCompactProtocol –更紧凑的二进制格式,处理起来通常同样高效。
TDebugProtocol –一种人类可读的文本格式,用来协助调试。
TDenseProtocol –与TCompactProtocol类似,将传输数据的元信息剥离。
TJSONProtocol –使用JSON对数据编码。
TSimpleJSONProtocol –一种只写协议,它不能被Thrift解析,因为它使用JSON时丢弃了元数据。适合用脚本语言来解析。
支持的传输协议有:
TFileTransport –该传输协议会写文件。
TFramedTransport –当使用一个非阻塞服务器时,要求使用这个传输协议。它按帧来发送数据,其中每一帧的开头是长度信息。
TMemoryTransport –使用存储器映射输入输出。(Java的实现使用了一个简单的ByteArrayOutputStream。)
TSocket –使用阻塞的套接字I/O来传输。
TZlibTransport –用zlib执行压缩。用于连接另一个传输协议。
Thrift还提供众多的服务器,包括:
TNonblockingServer –一个多线程服务器,它使用非阻塞I/O(Java的实现使用了NIO通道)。TFramedTransport必须跟这个服务器配套使用。
TSimpleServer –一个单线程服务器,它使用标准的阻塞I/O。测试时很有用。
TThreadPoolServer –一个多线程服务器,它使用标准的阻塞I/O。
正文
一、参考资料:
https://wiki.apache.org/thrift/ThriftUsageObjectiveC#Sample_Download
https://blog.csdn.net/xiaofei125145/article/details/52241803
二、环境配置:(推荐使用brew安装)
1、版本搜索
2、版本安装
3、卸载thrift
注意事项:
1、客户端配置的thrift版本要求和服务端版本统一
2、目前thrift版本为0.12.0支持swift语言,但是不太稳定(不清楚是不是使用问题)
3、推荐使用[email protected]版本,swift项目需要桥接,OC可直接使用
三、对接流程
1、准备工作:
(1)请先获取thrift协议文件,如下
(2)第二步打开终端, 进入存放thrift文件的文件夹中
(3)第三步我们需要把当前路径下的thrift文件转化成OC文件
(4)转化完成后会自动在当前路径下生成一个gen-cocoa文件夹,点开文件夹发现已经生成好的OC文件,我们只需要将文件拖入工程内,command + B编译,有错误进行修改。(迈向成功的第一步)
注意事项:
1、转译后的OC文件可能存在头文件导入、引用等相关错误
2、导入多份协议后可能会出现重命名等问题,出现此类问题可以全局搜索,需要手动修改类名(如果项目存在大量协议,为避免这样的问题可以规范好协议的命名)
3、进入对应冲突类中比对,并修改。
2、项目接入 (这里以0.9.3版本为例)
(1)Github搜索thrift, 在branches中找到相应版本,并下载该版本资源包
找到资源包lib/cocoa路径下的src文件夹,将该文件夹拖入项目中。
(2)项目中找到我们之前通过thrift生成的OC文件(以user文件为例)
可以找到类似@protocol nyUserServ 以及nyUserServClient类
(3)初始化方法,我们需要和服务端使用的协议保持一致,初始化方法也有区别,图例:case1、case2分别为不同协议的初始化方法
声明一个server/myService的对象,并初始化
(4)示例中,我们通过一个按钮的点击事件触发登录的响应,在nyUserServ协议中有提供了2个和服务器通讯的方法,我们根据不同的场景选择不同的方法
我们以action方法为例,首先初始化一个request对象,可以在ny_user.h中找到
这里的参数,我们可以需要跟服务端沟通好,其中可能会涉及到各种数据的加密解密(aes/sha/md5等)
图例中的r_type一个接口类型枚举,r_data是登录序列化后的字符串
上图serialize方法中传入一个泛型,约束其遵守TBase协议,TBase协议提供序列化以及反序列化所需要的write/read方法
(5)和服务器响应成功后会,返回一个response对象,我们所需要的数据包含在response对象中,接下来我们需要对response对象中的数据进行反序列化,反序列化之后才是我们能直观显示的数据
deSerialize返回返回一个T的泛型对象,反序列化的时候需要传入一个初始化的模型对象。数据填充完成后,然后返回改对象。loginRespPkt也是通过thrift转化生成的业务类,并不需要我们重新去定义
以上就代表这我们完整的完成一次数据请求到数据返回以及解析的全过程。当然这个结果是一路踩坑才实现的结果,接下来我会逐一描述其中的大坑。
四、疑难杂症
(1)多重协议文件内容业务类重命的问题
关于这个问题其实都是比较笨的方式,一协议命名规则约束,由于是跨平台的语言往往命名规则和个人习惯有很大区别,所以只能尽力去统一,二这是我们手动去修改了。
(2)数据加密解密问题(aes128/aes256等)
关于这一块有2个问题:
1、aes加密 iv偏移量需要前后端统一
2、aes128和aes256加密key的长度问题,前后端的加密解密key值要保持一致
(3)数据编码问题
1、编码问题,服务端返回的数据用utf8解码失败,用ASCII解码才成功,为了避免这样的问题,这里推荐数据的收发都通过data二进制数据交互序列化、反序列化直接通过data数据转化。