4.2 可靠的消息传输
如果CoAP协议头部中T字段标识为CON类型,则说明其采用可靠传输。CON类型的消息一般携带请求或响应,除非它是想要发送空消息以引发RST。接收端接收到CON类型消息后,必须是以下两种情况之一:
通过返回一个ACK消息确认已收到。回复的ACK必须带有和CON消息相同的Message ID,并且必须携带有响应(附带响应格式)或者为空消息(单独响应格式)。
如果是因为该消息缺少上下文而无法被正确处理(例如消息为空、使用了保留的Code类别(1,6或7),或者消息格式错误),拒绝这个消息。通过回复对应的RST消息,或者直接忽略,接收端可以拒绝CON类型的消息。回复RST消息必须带有和CON消息相同的Message ID,并且必须为空消息。参看5.2.1节和5.2.2节。
如果接收端想要拒绝一个ACK消息或者RST消息(例如ACK消息携带有请求或者有保留的code类别,RST消息不为空消息等),只需要忽略即可。一般的,ACK和RST消息的接收端必须不应答ACK或RST消息。
注意:发送端重传消息的间隔以指数增长,直到它收到一个ACK或者RST消息,或者达到最大重传次数。
重传由超时时间和重传计数控制。对于每一个CON类型的消息,发送端必须一直维护超时时间和重传计数,直到收到对应的ACK或者RST。对于一个新的CON消息,初始的超时时间被设置为介于ACK_TIMEOUT和ACK_TIMEOUT*ACK_RANDOM_FACTOR)之间(参见4.8节)的随机值(通常不是整数秒),重传计数被设置为0。当超时发生,且重传计数的值小于MAX_RETRANSMIT,消息被重传,重传计数增加,超时时间变为原来的两倍。如果在超时发生的时候重传计数达到了MAX_RETRANSMIT,或者收到了一个RST消息,那么就会放弃消息的传输,由应用程序来处理这个传输失败;如果在超时之前收到了ACK,那么传输就被认为成功了。
这一机制并不强制要求精准的时钟来实现上述指数回退算法。具体的说,某个端可能由于它周期性的休眠而没有赶上某一个重传时间点,但它却赶上了下一个。然而,两次重传之间的最小时间间隔是ACK_TIMEOUT,并且整个传输和重传的过程必须在MAX_TRANSMIT_SPAN(见4.8.2节)之内,尽管这意味着发送者有可能会错过传输的机会。
发送CON消息的端有可能在重传计数到达MAX_RETRANSMIT之前就放弃重传。例如,应用程序取消了这一请求,因为它已经不再需要响应;或者有其它证据表明消息已经到达,比如该请求消息导致接收端产生了单独响应,这种情况下就很明显,丢失的仅仅是请求消息的ACK而已,重传这个请求消息毫无意义。然而,响应端必须不能依赖请求端这种跨层的行为,它必须维护状态,为这个(可能重复的)请求回复ACK。如果需要的话,即使源请求端确认了CON响应(单独响应的第2步),接收端也应该回复(源请求端重传的请求)ACK。
另一个放弃重传的原因可能是收到了ICMP错误。如果希望处理ICMP错误以减轻潜在的ICMP欺骗攻击的影响,那么在实现上,应该仔细检查产生ICMP消息的原始数据,包括端口号和CoAP头部信息,如Message type, code, Message ID和Token;如果由于UDP提供的接口API的限制而无法检查,那么就应该忽略ICMP错误。如果遵循了第4.6节中的“实现注意”,那么正常情况下不应该发生数据包过大错误(IPv4的"fragmentation neede and DF set" [RFC0792])RFC4443],因此应该被忽略。如果没有遵循,那么就应该进入一个路径MTU计算算法[RFC4821]。Source Quench和Time Exceeded类型的ICMP错误应该被忽略。主机,网络,端口或协议不可达错误和参数错误有可能经过适当的审查后用于通知应用程序,消息发送失败。
最后更新于
这有帮助吗?