[从0到1搭嵌入式工程]设备与服务器后台通信的搭建

通过什么协议, 需要什么依赖,加密, 做什么通信,心跳保持,前后兼容问题。

1,设备与服务器后台通信,使用libcurl库, 使用http、https协议, 根据server API 构造URL,与server进行交互、请求、上传、下载等。

2,用HTTP还是HTTPS,使用HTTP协议,传输的文本会以明文的形式在互联网上传输,可能会被截取,查看, 使用HTTPS协议,消息会被加密后发送到网络上,中间数据被截到后,也无法解密。保证了安全性,HTTPS会有认证和解密过程,效率会低一些。对于不敏感的信息,可以使用HTTP,敏感信息,使用HTTPS。

3,使用HTTPS时,需要有证书的验证。

对于HTTP来说,我们在构建请求参数时关闭认证即可,curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 0L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 0L); 

对于HTTPS,除了开启认证之外,还需要指定ca证书, curl_easy_setopt(curl, CURLOPT_SSL_VERIFYHOST, 2L); curl_easy_setopt(curl, CURLOPT_SSL_VERIFYPEER, 1L);curl_easy_setopt(curl, CURLOPT_CAINFO, "/home/app/ca/myca.crt"); 这样,HTTPS在于server建立通信的过程中,就会使用ca与server进行认证,myca.crt由公司域名向ca认证中心申请得到。

我们使用浏览器访问https的时候,浏览器会帮我们加载网站的安全证书进行加密。但是我们用curl请求https时,没有通过浏览器,就需要自己手动指定一个安全证书进行加密。

CURLOPT_SSL_VERIFYPEER 设置为0 表示禁止 curl 验证对等证书(peer’s certificate)。CURLOPT_SSL_VERIFYHOST 设置为 1 是检查服务器SSL证书中是否存在一个公用名(common name)。注:公用名(Common Name)一般来讲就是你将要申请SSL证书的域名 (domain)或子域名(sub domain)。 设置成 2,会检查公用名是否存在,并且是否与提供的主机名匹配。 在生产环境中,这个值应该是 2(默认值)。

关于CA的扫盲贴,参考:https://kb.cnblogs.com/page/194742/

4, 不管用HTTP还是HTTPS,我们还需要使用自己的加密来保证, 请求的不可伪造性,保证后台的安全。

每一个请求,都会有带到服务器上参数,我们使用自己的密码,对这些参数进行加密,取hash值,放在请求参数里带到服务器,服务器收到请求后,再用密码也对这些参数加密,取hash值,如果hash值和收到的hash值一致,认为请求是有效的。

对于嵌入式来说,每一个设备在出厂的设备信息中,保存特有的密码值(或者写在代码中的hardcode密码), 用这个密码进行加密,以验证是我们的合法设备。

采用hmac加密方式为hmac-sha1,key=1234,有请求参数parama=a&paramb=b,调用hmac_sha1(),得到加密结果,进行base64编码,再把base64执行urlencode,编码成URL格式赋值给hmac变量, 在请求的参数中,再加入hmac=xxx这个密文,发送给server。server就可以通过这种方式对url进行验证了。

有了这些,我们就可以调用 curl_easy_perform(curl), 执行上面我们构造的请求了。


除了同步时间,下载固件,上传文件等常规功能需求, 我们要和后台做怎样的通信?

1,连接上网络以后,先把时间同步下来,设置到系统中去;

2,把设备的DID发送给服务器,检查DID是否是合法的。

3,把设备的运行信息,定期往服务器上报, 与服务器之间保持一个心跳。如果服务器在一段时间内没有收到设备发送的心跳请求,设备可能无网络或者掉电,认为设备离线。在这个请求中,可以把设备的网络情况、统计信息、功能开关等一些我们关心的统计信息,发送到后台,方便数据分析, 在请求的返回信息中,也可以加一些有用信息,供设备使用,比如设置到服务器上的设置。

4,创建一个单独的线程,负责心跳信号的保持,每隔一段时间(可以是两小时附近的随机值),发送一次请求, 避免网络原因,如果出错,可以重试发送。 同时注意在设备过多的情况下,将请求的时间点分散,因为时间上是从连上网以后的相对时间,所以理论上,不同的设备,是分散的。


兼容性

对于同一个功能的api,如果后台需要增加新的参数,而固件因为没有更新,还用原来实现的请求方法,当服务被部署以后,就会出现不兼容的问题。

为了避免不兼容的情况,我们就需要把同一个功能的api,分成多个,比如/v1/time, /v2/time, /v3/time, 他们实现同一个功能。对于最新实现的固件来说,可以使用v3的api请求,对于没有升级的固件,会依然使用固件对应的v1或v2版本进行请求,就解决了兼容问题。

猜你喜欢

转载自blog.csdn.net/bingyu880101/article/details/80249702