協議棧解析編程
藍牙的request/response安全
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命令就沒有這個問題,在同一個鏈接間隔中,你能夠同時發多個數據包,這樣將大大提升數據的吞吐率。你們能夠參考下圖來理解request和非request命令的區別:模塊化
經常使用的帶request的命令:全部read命令,write request,indication等,而經常使用的不帶request的命令有write command,notification等,完整的ATT命令列表以下所示:函數
NRF_SDH_BLE_OBSERVER用來爲本地文件(此處爲main.c)註冊一個BLE回調函數(此處爲ble_evt_handler),NRF_SDH_BLE_OBSERVER這個宏執行成功後,全部的BLE事件都會被ble_evt_handler捕獲。進入ble_evt_handler,你會發現BLE有上百個回調事件,你不須要每一個都處理,你只須要處理你關心的事件便可,好比鏈接成功事件BLE_GAP_EVT_CONNECTED或者鏈接斷開事件BLE_GAP_EVT_DISCONNECTEDspa
NRF_SDH_BLE_OBSERVER有一個很大的好處:某個模塊若是須要捕獲BLE事件,那麼它本身調用NRF_SDH_BLE_OBSERVER這個宏註冊相應回調函數便可,而再也不須要在其它文件中去註冊這個回調函數,將模塊的耦合性降到最低,符合模塊化編程思想。(即response包在應用層的回調函數)blog