Client和Server之间是通过ATT PDU来通信的,ATT PDU主要包括4类:读,写,notify和indicate。如果⼀个命令需要response,那么会在相应命令后⾯加上request;如果⼀个命令只需要ACK⽽不需要response,那么它的后⾯就不会带request。这⾥要特别强调⼀点,BLE所有命令都是“必达”的,也就是说每个命令发出去之后,会⽴马等ACK信息,如果收到了ACK包,发起⽅认为命令完成;否则发起⽅会⼀直重传该命令直到超时导致BLE连接断开。换句话说,只要你的BLE没有断开,那么你之前发送的数据包,不管它是⽤什么ATT PDU来发送的,它肯定被对⽅收到了。
我估计很多⼈对此会产⽣疑问,因为他们经常碰到丢包的情况,其实⼤家经常碰到的“丢包”,不是空中把包丢了或者包在空中被⼲扰了,⽽是⼤家发送的代码写得有问题,导致你要发送的包没有被安全送达到协议栈射频FIFO中,所以以后⼤家碰到丢包情况,请先检查你的代码,保证你的数据包正确完整安全地送达到协议栈射频FIFO中,只要数据包放到了协议栈射频FIFO中,蓝⽛协议栈就能保证该数据包“必达”对⽅。
既然每个ATT命令都必达对⽅,那么还需要request做什么?如果⼀个命令带有request后缀,那么发起⽅就可以收到命令的response包,这个response包在应⽤层是有回调事件的,⽽前述的ACK包在应⽤层是没有回调事件的。所以采⽤request/response⽅式,应⽤层可以按顺序地发送⼀些数据包,这个在很多应⽤场合是⾮常有⽤的。相反,如果你对应⽤层数据包的顺序没有要求,那么就可以不使⽤request/response形式。另外Request/response有⼀个副作⽤:⼤⼤降低通信的吞吐率,因为request/response必须在不同的连接间隔中出现,也就是说,你在间隔1中发送了⼀个request命令,那么response包必须在间隔2或者稍后间隔中回复,⽽不能在间隔1中回复,这就导致两个连接间隔最多只能发⼀个数据包,⽽不带request后缀的ATT命令就没有这个问题,在同⼀个连接间隔中,你可以同时发多个数据包,这样将⼤⼤提⾼数据的吞吐率。