前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >RPC(三)

RPC(三)

作者头像
小闫同学啊
发布2019-07-18 15:45:20
1.5K0
发布2019-07-18 15:45:20
举报
文章被收录于专栏:小闫笔记小闫笔记

正文共:2794 字 5 图 预计阅读时间:7 分钟

每日分享

One's destination is never a place but rather a new way of looking at things.

一个人的目的地永远不是一个地方,而是一种看待事物的新方式。

小闫语录:

物质永远不是最终归宿,精神才是奋斗的最终目标。

RPC

前面文章导航:

RPC(一)

RPC(二)

没有看过之前文章的小伙伴,直接点击传送门(上面的标题即链接,跳转对应内容即可)。

1.消息协议设计

接着上一篇文章,我们继续讲解消息协议相关内容。最近因为各种原因,又间断了几天,也许以后还会间断,哈哈哈,但是RPC相关内容不会断掉。大家也可以休息一段时间,在某个周末集中学习,我一有时间就会继续更新。所有的RPC相关文章会为大家汇总到『.py笔记』下的『分类合集2』中,大家可以在专栏中找到。那么我们切入正题,开始今天的学习吧。

消息协议设计的时候,我们分成两部分内容,一部分是调用请求消息(也就是发起调用的时候,请求数据如何组织),一部分是调用返回消息(即调用完成之后,返回的数据如何组织)。

1.1调用请求消息

还是接着上篇文章除法的小案例继续讲解今天的内容,首先看第一个要传递的数据--divide。这是一个字符串,它可以 采用二进制的方式进行传递,将其每个字符所占用的字节传输即可。那么怎么做呢?我们这样处理:

比如divide占6个字节,为了系统识别出来divide,我们需要考虑边界问题,告诉系统从哪开始,从哪结束。按照长度声明的方式,需要在前面加一个数字,表示divide数据的长度。6是整数,按照在计算机中4个字节表达整数的方式,表示为 0110。这样一来,系统先识别到4个字节,然后将其转换为整数类型,知道divide占6个字节,然后直接往后读取6个字节。到此为止,divide这个方法名读取完毕。关于字符串的数据以后就按照上述方式进行传输。

接下来我们再看第一个参数num1,为整数类型。我们仍然采用4个字节进行表达传输。但是有一个问题,就是divide字符串和num1是作为整体传输的,计算机怎么知道divide后面的数字是num1还是num2参数的值?也许你会想,这个简单啊,我们直接在前面跟一个参数名字,用上面讲到的字符串传输方式不就好了吗?可以是可以,但是你没发现数据因此变得很大,会造成浪费吗?比如我的参数名叫做 divide_num1_value,然后参数的值为1。为了传输一个1,你需要多浪费多少字节?这样是不是不利于节省传输时间?那么怎么办呢?容我慢慢道来。我们可以通过指定一个数字,比如num1我们用1指定,num2用2来指定。这样,读取完divide之后,先读取到1,就把接下来的数据放到参数1的位置,读取到2,就把下个数据放到参数2的位置。这样就节省了一定的空间。到此为止,参数的传输也完成了。我们在传递数据的时候,只需要将方法名、参数1和参数2整合到一起传递即可。

我们在指定参数的时候,不需要占用4个字节了。因为一个方法中,参数往往不是很多。一个字节8位,也就是256个数,足以表示。

有人会问了,你骗人,那个默认值你还没有讲呢。小伙子,记性不错嘛,接下来我们就考虑一下默认值的情况。

由于参数2设有默认值,可传递也可不传,所以整体消息的长度就不能确定了,那么传递过去,计算机怎么知道消息是不是传完了呢?其实这种情况很好解决,可传递可不传递,我们仍然采用长度声明法,在整体消息中放置一个消息长度,用4个字节的整数表示。读取到长度为多少后,先读方法名,在读参数1,如果到达了边界就说明消息读完了。没有到达边界,我们就继续读取参数2。那么整体消息的长度放在哪呢?有两种方案:

方案一:

放置在消息最前面,先读取四个字节整体消息长度,然后再读取4个字节方法名消息长度,然后读取方法名,再读取参数1,如果没到达边界,再读取参数2.

方案二:

放置在方法名字符串后面,先读取四个字节方法名长度,读完方法名后,读取参数的长度,先读取参数1,读完如果没到达边界,再读取消息2.

我们后面的案例中,采用的正是方案二。

1.2调用返回消息

接下来,我们说一下返回消息怎么设计。返回消息按照之前的案例,有两种情况:一种情况是正常(返回一个float类型),一种情况是异常(由于我们之前自定义了异常,异常只有一个值便是message,它是字符串类型)。两种情况怎么传输呢?结合上面的例子,大家动脑想一下。

好了,不卖关子了,直接说结果。float类型,我们还是采用4个字节进行表示,异常采用字符串的处理方式。那么计算机怎么知道消息是float类型,还是字符串呢?我们可以在前面消息前面再加一个字节,比如用1表示正常,2表示异常,这样的话计算机能区分开了,我们也尽可能的精简了数据大小。

有人会有疑问,用不用加长度声明,解决边界问题呢?其实不需要了。我们之前长度声明是因为数据整体的大小不确定,消息有长有短。而现在我们在前面添加的1和2既表示了正常和异常的情况,同时也声明了长度。正常就是float类型,4个字节;异常就是字符串,直接读取就好了。

2.struct模块

我们已经知道消息协议如何设计了,接下来就需要考虑到如何实现的问题。在此我们引出struct模块,它是Python标准库提供的二进制编码解码库,允许我们将各种不同类型的变量转换为bytes字节类型,或者反向转换。有了它我们实现就容易的多了。

2.1将其他类型转换为bytes类型
代码语言:javascript
复制
In [1]: import struct
In [2]: struct.pack("!I", 6)
Out[2]: b'\x00\x00\x00\x06'

我们是使用 pack方法进行转换的。它接收两个参数,参数一为按照什么格式进行转换,参数二为数据。输出的结果为bytes类型。

一:b打头代表的就是bytes类型数据。其中 \x00类型的东西代表的是一个字节,可以看到有4个字节。其中前三个字节一个0代表4位,两个0正好代表8位。 \x06代表的是,我们传输的数据为6。 二:pack中第一个参数 !I里面有两个符号,分别代表如下内容: !:表示适用于网络传输的字节顺序。 I:表示无符号4字节整数。

2.2将bytes类型转换为其他类型
代码语言:javascript
复制
In [4]: struct.unpack("!I", b'\x00\x00\x00\x06')
Out[4]: (6,)

我们使用 unpack方法进行转换。里面参数同上一部分说明。需要注意的是,返回的结果是一个元组,我们取值的时候可以通过下标来进行。

优质文章推荐:

redis操作命令总结

MySQL相关操作

SQL查询语句

前端中那些让你头疼的英文单词

Flask框架重点知识总结回顾

团队开发注意事项

浅谈密码加密

Django框架中的英文单词

Django中数据库的相关操作

DRF框架中的英文单词

DRF框架

Django相关知识点回顾

python技术面试题-腾讯

本文参与 腾讯云自媒体同步曝光计划,分享自微信公众号。
原始发表:2019-05-09,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 全栈技术精选 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 每日分享
  • RPC
    • 1.消息协议设计
      • 1.1调用请求消息
      • 1.2调用返回消息
    • 2.struct模块
      • 2.1将其他类型转换为bytes类型
      • 2.2将bytes类型转换为其他类型
相关产品与服务
云数据库 MySQL
腾讯云数据库 MySQL(TencentDB for MySQL)为用户提供安全可靠,性能卓越、易于维护的企业级云数据库服务。其具备6大企业级特性,包括企业级定制内核、企业级高可用、企业级高可靠、企业级安全、企业级扩展以及企业级智能运维。通过使用腾讯云数据库 MySQL,可实现分钟级别的数据库部署、弹性扩展以及全自动化的运维管理,不仅经济实惠,而且稳定可靠,易于运维。
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档