67,541
社区成员
发帖
与我相关
我的任务
分享
1. 遇到扯皮的事情,我一般会把多种情况都拆分开来进行解决。
A.登录认证成功了,心跳也正常了,但是,设备还是离线的,那说明,网关或者服务端出现了问题,这是很明显的,没必要扯皮。
B.登录认证成功了,心跳也正常了,设备也是在线的,但是,服务端处于僵尸状态,没有任何反馈,这个问题到底出在哪儿,不能武断的下结论,要先把场景重现出来,找客户端和服务端进行联调。以我的经验判断,如果客户端发送数据及时清空了发送缓冲区的话,大概率还是服务端的问题。
2.设备的状态(在线、离线),有的服务端保存在缓存中,有的服务端做了持久化操作,两种方式各有优点。
在缓存中的信息可以实时更新,但是,查询相对麻烦,我是说编程复杂度比较大,因为,一般情况下,和设备终端连接的服务端,那个玩意叫网关,只负责连接设备和转发数据(不同协议之间要进行转换),而查询设备状态的服务端会另外开发一套程序,有的是管理后台模式的,有的是网站形式的,两个服务端要建立数据通路才能把实时数据弄过来。如果进行了持久化,数据库就是这个通路了。但是,采用持久化方案就会产生网关重启(包括意外重启)状态没有进行重置的问题,如果系统由多个网关构成,那么,重置状态就不能由网关来做了,还要另外找一个单点服务,或者,分布式任务来定时的(或网关重启触发的)重置数据。
下面聊一下通信协议相关的事情:
1. 数据格式
A. 采用分隔符还是长度字段来区分数据包,各有优缺点。采用分隔符应该是考虑到组包拆包比较方便,降低了单片机的编程复杂度。带长度字段的数据包要测量包体的长度,组包拆包都比前者复杂。至于说拆包效率,带分隔符的拆包效率应该高于带长度字段的数据包,因为运算相对简单。
B. 认证信息,一般是由设备码(或者用户ID)和密码组成,以后的每个数据包一般都要带上设备码(或者用户ID),理论上可以不带,但是,带上有带上的好处。当然,密码就不要带了,带上密码就失去了认证的意义了。有的协议是在认证之后反回一个认证令牌,每次数据交互都带着令牌。作用都一样,就是识别终端设备(或者用户)。为啥非要带上设备码?因为有的系统,你看着是一个服务端,其实后面是一个服务器阵列,你这次交互的数据可能分给1号服务器来处理了,下一次交互的数据就分给别的服务器来处理了,为了容易识别客户端就带上了设备ID。所以说,理论上是可以不带的,因为认证成功后,TCP连接就代表了设备,但是,实际上,为了系统的扩展性,还是要带上设备ID。
C. 包尾的校验字段的作用有两个,一个是防止数据传输错误,当然,如果承载协议是TCP协议的话,可以不必考虑数据传输错误的问题。但是,有了这个校验码,在编程的时候就可以很方便的检查组包拆包数据是否存在人为的错误。另一个作用是防止网络入侵,就是说终端的数据先经过第三方的节点,将终端发送的某些数据更改后再转发到服务器,这个时候,校验码不失为一种防御手段,虽然很容易被破解。但是包尾校验码,一般在物联网的数据通信中(尤其是底层通信中)都是常常被采用的,可以很大概率的确保收到的数据不是被更改过的。相比数字签名的签名算法,异或(同或)算法是最简便的一种。
D. 为啥不考虑TLS加密,证书认证?主要原因还是因为单片机的计算能力,以及研发成本吧。物联网的概念里面就是万物互联。万物里面有PC机,PAD这种计算能力很强的设备,也有洗衣机,热水壶这种计算能力很低的设备,所以,在设计通信协议的时候,可能会考虑降低计算量和复杂度。
楼主的想法,可能是把客户端当成了PC机了吧,我感觉讨论的东西,都比较偏向于相对较复杂一些的应用程序开发,而且,有时候还觉得会造成服务端的计算过于复杂的问题。服务端,我觉得没有太大的必要降低计算复杂度,服务端可以优化代码或者优化架构,关键问题应该是怎样降低客户端或者说是数据终端的计算复杂度。等什么时候,所有的客户端都由操作系统构成,内存都2G开外了,那么,计算能力应该就可以适应一些复杂的计算了。我觉得这是一种趋势。但是对于更简单的数据终端而言,相对精简一些的通讯协议,更加适用。没有最完美的协议,只有更适合的协议。如果公司肯投钱,搞两种以上的协议也不是问题。