我使用gen_tcp
通過TCP在Erlang接收消息。按照{packet, 4}
選項的規定,通過使用4字節長的報頭將數據流分成數據包。這是我怎麼稱呼gen_tcp:listen/2
:如何處理Erlang中TCP流中數據包的錯誤長度標頭?
gen_tcp:listen(Port, [binary, inet, {active, once}, {packet, 4}]).
正如你所看到的,我用的是{active, once}
選項,這樣我可以毫不淹沒它取從工藝郵箱我的包。只要長度標題正確,此工作正常。如果不是,任何事情都可能發生。所以我想以某種方式處理錯誤包的可能性。
這有點棘手,因爲我實際上正在處理一個流。忽略錯誤的數據包會沒問題,但是我怎麼讓Erlang跳過這些數據包並識別下面的數據包?這個問題通常如何處理?
使用分隔符更好嗎?我已經看過gen_tcp
的其他packet
選項。尤其是以下幾點:
asn1 | cdr | sunrm | fcgi | tpkt | line
唯一一個我真正理解的意思是line
,但我不認爲這是一個不錯的選擇。我期待接收在Objective C中發送和構建的包,這是我不熟悉的,它包含許多不同類型的數據,不僅包含字符串。
感謝您的回覆,大衛。我想我會堅持長幀,並依靠正確實施的協議。我正在考慮一個解決方案,在'receive'子句中經過一段時間之後,套接字的緩衝區將被刷新,表明沒有收到數據包或者緩衝區中的下一個數據包是錯誤的,並讓客戶端重新發送消息。不過,我還沒有想出在主動模式下刷新套接字緩衝區的方法。我嘗試切換到「被動」模式並調用'recv/2',希望它能做到這一點。它沒有。 (爲什麼?) – Max
如果您使用的是{packen,N},則無法刷新它。如果您自己實現了成幀,則始終可以在套接字讀取上超時。沖洗緩衝區永遠不是一個好的選擇,雖然...說你的超時時間是5秒,而你的客戶端發送3000字節。你的MTU大概是1500字節,所以你得到兩個1500字節的數據包。但是如果另一端掛起呢。假設它位於實時遷移的VMWare節點上,或者您有某種類型的GC暫停或某種情況。您只會刷新前1500個字節以獲得另一個1500字節的錯誤數據包。 –