我们在一个IoT场景中工作,Thing / Constrained设备定期将其GPS位置发送到给定服务器。受限设备是一块类似于Arduino的板,该板由电池供电,并使用GSM / SIM屏蔽罩进行连接。这些是我们的设计目标:


最大程度地延长电池寿命
最小化数据传输

出于测试目的,我们使用HTTP产生了大约500字节的消息,但是现在是时候使用更合适的协议进行数据传输了。数据传输的一些特征如下:


有效负载很小,通常少于50个字节(与典型的MTU距离很远,也就是说,所有内容都应适合IP包)
数据应大约每分钟发送一次。差异并不重要。
可以丢失一些消息

现在,该设备不需要服务器的任何响应(但是,将来可能会改变) 。服务器也不必开始与设备的任何对话。到目前为止,我们已经想到了以下可能性:




基于TCP的自定义协议。这将摆脱HTTP标头,使消息小10倍。这是我们可靠/保守的方法。

基于UDP的自定义协议。由于UDP的标头较小,并且没有开销,因此我们希望它非常有效。如所评论的,在此处丢失一条消息或无需担心...但是,可能还有其他我们不了解的不可靠性问题。

MQTT(TCP上的标准):与TCP相比,几乎没有任何开销,因此这也是一种选择。但是,我们在GSM / SIM技术方面经验不足,也不知道连续的MQTT连接如何工作方式,以及连接心跳带宽对于这种低频数据传输是否值得。

CoAP(UDP上的标准):看起来也很有希望。标头和UDP工作仅4字节开销。但是存在未知的UDP风险。

有人可以提供任何提示吗?提前谢谢。

评论

在这种情况下@RichardChambers,可靠性不是那么重要。我们有能力在这里或那里丢失一些包裹。不需要烧伤。我认为在UDP之上进行可靠性工作没有太大意义,这就是TCP的用途。

我不会通过设计自定义协议来重新发明轮子。 CoAP与MQTT的比较会为您提供更多注意事项。您是否需要对解决方案进行过时的验证,即将来要处理更严格的要求(损失保证,响应时间,互操作性等)?设备是否经过NAT?网关后面是否有设备分组?许多未知数...

#1 楼

关于我在TCP,UDP和MQTT方面的经验的几点思考,以及一些需要复查的其他资源。

使用UDP,我遇到了静默故障问题,即一个网络节点上的应用程序,客户端,只能看到已发送的某些UDP消息。网络流量可能出问题的原因太多。 UDP的问题在于,只要在数据包生产者和数据包使用者之间的网络路径中的任何节点都可以保证,就可以丢弃很多数据包。请参阅Wikipedia主题数据包丢失。

问题是,在当前网络环境下,丢失率是多少?因此,如果这是LAN或子网内的通信,则丢失率可能很低。在WAN或整个Internet上,您的丢失率可能很高。 UDP数据包由于多种原因而被丢弃并路由,但是网络条件允许该跳数递减。

在您的情况下,只是一个简单的ack,在超时后重新发送而没有收到ack就足够了。 />
我已经通过维护的TCP连接完成了XML消息,并且效果很好。我有一层将完整的消息分别在缓冲区中传递给应用程序层进行处理。我使用XML来打包消息,并使用XML开头标签作为消息的开头,并使用XML结束标签来知道何时接收到整个消息。

TCP确实具有一些功能,例如顺序数据包的顺序,没有重复,并且作为连接的传输机制意味着您知道另一端是否消失,尽管可能需要一段时间才能找到。尽管网络条件会导致TCP吞吐量降低,但在正常情况下,连接和断开连接会带来延迟,但不会带来麻烦。

MQTT是由网络传输层(通常为TCP)传输的协议。 MQTT使用发布/订阅模型,因此没有消息存储。因此,如果发布者发布消息(如果订阅者当时未连接),则发布者发布消息时将看不到该消息。 MQTT几乎是实时的,我想这就是首字母缩写词的遥测部分的全部内容。我确实喜欢将MQTT用于小消息,并且已经通过使用Mosquitto的MQTT通过JSON有效负载进行了一些实验。请参阅本文,使用Mosquitto(MQTT)可靠地传递消息,并概述MQTT和服务质量。并查看这篇简短的文章,其中包含指向资源的链接,其中包括示例应用程序IoT – MQTT发布和订阅者C代码。

我在MQTT上使用JSON文本和订阅者中的SQLite3数据库存储消息的实验是在https ://github.com/RichardChambers/raspberrypi/tree/master/mqtt,尽管源代码是C语言,而且非常凌乱。

这是一个13分钟的视频#144互联网协议:CoAP vs MQTT,网络嗅探,以及为宜家Tradfri骇客做准备。这是一篇关于CoAP(受约束的应用程序协议)的有趣文章:CoAP是物联网的“现代”协议。 CoAP的摘要如下:


早期采用者同意约束应用协议对于约束网络和设备非常有效。
众所周知:“在非常拥挤的无线网络上-Wi-Fi或蜂窝网络
-CoAP可以在MQTT这样基于传输控制协议(TCP)协议的地方继续工作。”甚至无法完成握手。” Vermillard说。

这是因为与大多数其他IoT协议不同,CoAP是基于UDP构建的。换句话说,这意味着没有TCP遇到的协议握手或错误纠正。 “ CoAP可能不如HTTP
可靠,或不能保证像MQTT这样的消息的传递,但它非常
Matthieu指出,“如果您没收到某些邮件没问题,可以在同一时间段内发送更多邮件。”


您可能还会看到其他一些东西,例如AMQP,STOMP和CBOR。请参阅CBOR标准网站以及本文,CBOR协议的实现和评估。请参阅本文,选择消息传递协议:AMQP,MQTT或STOMP比较并对比了AMQP,MQTT和STOMP,并以关于RabitMQ代理的注释结尾:


希望这可以帮助许多人开始研究协议的解决方案
在每种用例中,由于公司
拥有许多具有不同需求的应用程序是很普遍的,因此肯定有可能
,您可能需要在不同应用程序中同时使用所有三个代理。这就是
像RabbitMQ这样的可靠的多协议,多语言经纪人进入的地方
-因为它可以向其中发送STOMP,MQTT或AMQP并获取另一个
出去。您无需受这些协议之一的束缚-RabbitMQ代理支持所有
三个协议,这使其成为应用程序之间互操作性的理想选择。插件体系结构
还使RabbitMQ能够在将来发展以支持这些协议的其他版本或更新的
版本。


此幻灯片共享软件包包含约60张幻灯片四种不同的物联网协议之间的比较和对比,研究了两个不同的物联网组(消费者和工业)的需求,它们对可靠性和鲁棒性有不同的需求。什么是物联网的正确消息传递标准?。

#2 楼

听起来像是UDP的完美应用程序:客户端-服务器拓扑(不需要pub / sub),可承受数据包丢失以及单个数据包传输之间的巨大差距意味着无序到达不是问题。

节省的连接建立和数据包开销将对您有利。

您只需减轻静默故障问题即可。有很多方法可以做到这一点,但是我的建议是让服务器在每次接收到x(例如10)个数据包时做出响应。这样,客户端就可以知道有多少个数据包正在通过,并且如果它低于阈值,则可以提高传输频率以抵消丢失的数据包。如果什么都没有通过,那么TCP仍然无济于事,所以最好还是将客户端置于遇险模式,直到情况消除为止。

通过Internet的UDP数据包丢失通常不会高,如果是的话,通常是暂时现象。 GSM提供了一些缓冲和无线电信号评估功能,因此无论如何都可以抵抗杂散噪声。

#3 楼

您是否在外部受到限制才能使用GSM / SIM?

一种替代方法是使用LoRa网络,该网络:


针对小型有效载荷进行了高度优化
,其设计目的是使能耗最小(因此最大电池寿命)
设计范围很远
具有连接类别(始终打开,已确认,未确认)
具有计划的下载窗口(例如,用于固件更新或RX ACK)

您可以插入大多数国家的现有社区或商业LoRa基础设施,或者如果合适的话,可以部署自己的LoRa集线器。

全球范围内都有积极的开发,并且原型屏蔽罩的可用性很容易(例如Arduino)。

评论


问题中提到的每分钟一次太频繁了,无法满足建议的LoRa节点传输间隔。

–克里斯·斯特拉顿(Chris Stratton)
18-2-4在7:47

同意1分钟太频繁了。尽管@bgusach没有提及该应用程序。如果可以对有效负载进行二进制编码以减小大小,并且可以使用3-5分钟(甚至10分钟)的间隔,那么它可能是理想的选择。无论如何,只是一个建议,正如我注意到的那样,答案中没有提到过。

–布伦丹·麦克
18年2月4日在8:21

是的,如果我没看错的话,大概每四分钟间隔50字节这样的内容不太合适;但这需要验证,很容易至少减少两倍。

–克里斯·斯特拉顿(Chris Stratton)
18-2-4在8:33



有趣,但是我们受到GSM / SIM的限制(这旨在成为一种消费品,可以在没有电话网络的任何基础设施的任何地方购买和使用)。

– bgusach
18年2月4日在14:10

#4 楼

我希望使用带有JSON数据的最小HTTP响应... HTTP响应可以远远低于500字节HTTP传输,并且您仍然与RESTful Web应用程序的许多客户端兼容。

最小HTTP消息(例如带有JSON结果的)带有aprox 130字节的HTTP数据如下所示:

HTTP/1.1 200 OK
Server: ProprietaryAndroid
Connection: close
Content-Type: application/json
{
  "lat": "42.00000",
  "long": "10.00000"
}


如果您只想将数据从应用程序发送到服务器,则可以简单地使用一个HTTP GET,可在其中将lat / long设置为URL参数。该请求的数据甚至少于响应。

GET /?lat=42.00000&long=10.0000 HTTP/1.1
Host: 192.168.0.2 
User-Agent: Proprietary
Accept: */* 
Connection: close


评论


感谢您的回答,但是HTTP响应我看不到您的意思。我们要摆脱整个HTTP协议,以节省数据传输。最重要的是,使用GET修改资源是Wrong Thing™要做的

– bgusach
17年12月20日在9:13



从Architectutal方面同意您的看法,其他动词(如POST)(作为通用动词)同时在REST API中更常见。取决于您要开发REST API的成熟度级别。只是想展示如何最大程度地减少HTTP,同时又能保持简单的实现和与现有框架(客户端和服务器)的兼容性,同时又能保持人类可读性。用响应样本进行回答令人困惑...如果您想发送数据,那么您当然会使用POST或GET消息-如果是POST,请使用我在第一个样本中显示的json内容。

– Christophh Bimminger
19年2月16日在17:29



#5 楼

没有“最佳”协议。您需要进行很多权衡:


您的设备是否会在随机网络上被随机端口阻塞?如果是这样,使用HTTPS可能会更好。
如果发送UDP,则每次总是可以发送最后N次测量,因此忽略了很小的数据包丢失。您还可以发送ACK数据包,从而将UDP转换为可靠的协议。 (大多数基于UDP的协议都可以做到这一点。)
您的客户是否关心他们的数据是否未加密地公开?您的客户是否会担心黑客是否可以将不良数据注入到那些未加密的连接中? (如果是,则可能需要加密。)
如果有人嗅探您的协议并操纵数据会怎样?您可以防止一台设备覆盖另一台设备的数据吗?
您最多可以拥有几台设备?您将如何处理所有这些设备?您如何将数据路由到需要去的地方?您如何处理服务器基础结构的维护和升级?如果您没有经验,则可能是高估了处理许多同时连接的能力。最好外包给供应商(并使用其协议,例如AWS IoT)。


#6 楼

我们有比较HTTP和MQTT传输速率的精确测试,请参见test2,在您当前的情况下,MQTT将为您带来比HTTP少50倍的流量(和电池)。

MQTT和普通之间基本上没有区别TCP(消息大小)。我什至会说,MQTT有效负载中的纯TCP和二进制消息与JSON之间基本上没有区别。这样,使用MQTT + JSON并依靠此技术进行数据传递和表示要方便得多。只需将您的密钥命名为或多或少简短即可。

关于UDP,如果每分钟传输一次,则最好使用TCP。如果传输是每10-20分钟或更长时间一次,则您可以将UDP视为更有效的通信/电池解决方案。如果您尝试使用ACK开发自己的协议,我建议您使用MQTT或TCP并专注于您的业务案例。

一般来说-实现它越简单,就可以在其中实现最佳结果。最短的时间。如果我是您,那么在那种情况下,我最好测试UDP +自己的二进制格式和MQTT + JSON,然后选择其中之一。甚至只是从MQTT + JSON开始,然后考虑是否适合我的情况。

评论


我将在这里提及针对UDP的几句话。我们维护着大型SaaS GPS车队管理系统(连接了超过100万辆汽车),在全球100多个国家拥有客户。最近,我们发现美国的互联网提供商出于某种原因(甚至对于M2M应用程序)也阻止UDP数据包从美国流出。它开始于几个月前,但是非常痛苦,因此我建议您选择基于TCP的协议(MQTT)并依赖于全球标准。有朝一日,在某些国家,您甚至将被迫在Websocket上使用MQTT来维持连接。只是很小的建议。

–shal
18年3月19日在20:25