~
超時是每個程式設計師學習串列埠程式設計最初結識的引數,雖然超時的效果不是很理想,但超時是最簡單的方法。
超時的判定有兩種實現,一種是接收到最後的碎片開始計時,直到計時完畢就觸發超時事件;另一種是用時鐘脈衝來區分時間片,如果某乙個時間片沒有收到碎片,就觸發超時事件。
顯然,分時間片的方法需要有乙個後台時鐘執行緒,多出來乙個執行緒就多出來乙個麻煩。不建議使用劃時間片的方法。
考慮到開發難度,微控制器程式可能只有超時限制,這時只要不間斷地對微控制器進行傳送,微控制器的記憶體就會重複溢位,然後一直觸發看門狗,重複復位,導致程式無法正常執行。這就是對微控制器的串列埠攻擊。可見如果執行環境的安全性得不到保證,不論是微控制器還是上位機,都不可以僅僅依賴超時。
~正常的報文總是乙個有限的數字。可想而知,假設存在一種無限長度的報文,那麼目標機器永遠無法完成報文接收,也就永遠無法執行操作,這個報文也就沒有意義了。沒有意義的報文屬於網路攻擊,不是正常的通訊。我的建議是作為接收端的程式,不需要幫助完成網路攻擊。每一種通訊規約都包含有乙個長度限制,比如modbus約定報文長度限制256位元組,mqtt約定長度限制0x1fffffff位元組。不得不說,有些規約的長度約定實在太長了,幾乎超過了作業系統為應用程式分配的記憶體空間。這種情況下預期長度基本上不起作用。但是通常的報文實際長度總有乙個比較小的上限。我見過的最長的modbus報文也就30多個位元組,最長的mqtt大約1kb,645規約30個位元組也差不多了。
有了長度限制,就可以很好地防止通訊干擾的情況下無限接收的故障。對於固定長度的報文,預期長度的限制是乙個很好的避免最終超時以節約時間的方法。
~預校驗是指在接收過程中,對報文質量的判定。它包括預確認和預丟包兩種情況。
對於有報頭和報尾的規約,可以在接收過程中檢查報文格式是完整性。當出現沒有報頭的情況下,可以不等待後面的資料,直接返回已經收到的錯誤資料片(薦)或清除快取重新下一輪接收。如果檢測到格式已經完整,則可以直接返回合格的報文,不再進入超時等待的過程。
對於格式不封閉,但有校驗碼的規約,可以用校驗碼先行判定報文是否已經完整。理論上講,格式不封閉的規約有可能碰巧讓不完整的報文碎片通過驗證,但概率極小,而且還可以通過提前解碼進一步確認報文碎片是否合格。
當判定報文碎片合格或完整以後,就可以直接返回,節省了無意義的超時時間。無明確判定時,進入超時等待,試圖讓報文完整。當判定報文碎片不合格的時候,有兩種選擇,一是返回不合格的碎片,二是清除快取,重新接收。我推薦的是返回不合格的碎片,讓邏輯層去丟包。多數情況下,傳送端無法確認自己的資料被丟棄。等待的結果一般就是白忙活一場,浪費時間而已。而把不合格的碎片交給邏輯層,邏輯層可以更快地下令發起新的訪問,反而節省時間。
/**
* 資料拼接地接收
* * @deprecated 如果輸入io是長期阻塞型,則會卡死。
* @param io
* @param timeout
* @param linelimit
* @param breakcondition
* @return
*/public
static
communicationmessage
> message_type receivewithdatastitching
( communicationio
io,int linelimit, predicate<
byte
> breakcondition)
/** * 資料拼接地接收
* * @param io
* @param timeout
* @param linelimit
* @param breakcondition
* @return
*/public
static
communicationmessage
> message_type receivewithdatastitching
( bufferedreceivable
io,long timeout,
int linelimit,
predicate<
byte
> breakcondition)
/** * 資料拼接地接收
* * @param supplier
* @param timeout
* @param linelimit
* @param breakcondition
* @return
*/public
static
communicationmessage
> message_type receivewithdatastitching
( supplier
supplier,
int linelimit,
predicate<
byte
> breakcondition)
lastrecvmsg.
accept
(abuffer.
tobytearray()
);return staticdatautils.
castobject
(lastrecvmsg);}
if(recvmsg.
get(
)== null)
lastrecvmsg = recvmsg;
// 避免返回型別為communicationmessage而需要的返回型別是其子類造成型別轉換錯誤
abuffer.
write
(recvmsg.
get())
;byte
currentbytes = abuffer.
tobytearray()
;if(currentbytes.length >= linelimit)
if(breakcondition != null && breakcondition.
test
(currentbytes))}
}catch
(ioexception e)
}
成功三要素
乙個人要想成功,以下三要素是必不可缺的。1 努力。乙個人成功的人士,必須有為了自己的事業拼搏的那種執著。乙個沒有恆心,不能吃一點苦的人,成功的可能性是很渺茫的。完成一件事情,興趣很重要,但不能只憑興趣。因為一件事情,不會是從開始到結束都是能讓你鬥志昂揚的。他會有一段平淡期,甚至低谷期,這時候,就需要...
事件三要素
dom 文件物件模型 bom 瀏覽器物件模式 js以事件驅動為核心的一們語言 事件三要素 1 事件源 a 執行者 b 誰引發的事件,事件的標籤,動作 2 事件 a 執行的事情 b 已經定義好的 點選,滑鼠移上 3 事件驅動程式 處理元素 a 執行結果 b 對樣式和html標籤的 dom操作 執行事件...
成功三要素
乙個人要想成功,以下三要素是必不可缺的。1 努力。乙個人成功的人士,必須有為了自己的事業拼搏的那種執著。乙個沒有恆心,不能吃一點苦的人,成功的可能性是很渺茫的。完成一件事情,興趣很重要,但不能只憑興趣。因為一件事情,不會是從開始到結束都是能讓你鬥志昂揚的。他會有一段平淡期,甚至低谷期,這時候,就需要...