編寫了一個TCP的多客服端線上網路電子詞典,本地測試時一切良好。當把服務端一掛在公網上,立馬就會發生問題。如果網路狀況非常好一切也正常,但網路一差,服務端和客服端都會接收對方重複傳送的訊息,網路越卡越明顯。
回覆列表
-
1 # 遷徙de麻雀
-
2 # 喲喲吼說科技
如題,TCP是無法過濾掉因網路延遲而造成二次重發的訊息,至於原理是什麼,那就需要了解TCP重發機制是什麼。
TCP超時重傳機制:超時重傳是TCP協議保證資料可靠性的一個重要的機制,在傳送出某一資料後會開啟一個計時器,若在一定時間內沒有收到迴應的ACK報文,那麼啟動重傳機制,重新發送資料,直至該資料傳送成功為止。直接導致重傳的引數就是RTO(重傳超時時間),此時間的設定會直接影響到資料在傳送後多久沒有收到會啟動重傳機制,設定過大過小都會影響TCP協議的正常使用。
若RTO設定時間過長,那麼傳送端在傳送出資料後會經較長時間才能發現數據丟失丟失,嚴重降低了資料傳輸的吞吐量;
若RTO設定時間過短,那麼傳送端就會在很短的時間確認資料是否丟失,會造成部分因延遲大而沒有接受的資料報文段誤認為丟失,造成沒必要的資源浪費。
像題者這樣只能去把網路調整好,減少網路延遲,或者根據所需時間設定RTO。
題主,你的問題不能透過TCP來解決,並且跟TCP的超時重傳也沒有關係。
雙方都接到重複訊息,是因為本身就透過Socket介面讓TCP重複發了訊息。這個可以透過在傳送介面記錄日誌來驗證!當然也只能在應用層設計解決方案。
TCP不背鍋TCP的可靠性不是跟我們開空頭支票。
Tcp分組的序號,除了保證資料有序,還會丟棄因為超時重傳導致的重複分組!重複的分組並不會交給應用層。
TCP使用了指標退避的倍乘關係來最佳化重傳策略,不太必要去調整什麼RTO(針對另一個回答而言)。
如果題主可詳細參考《TCP/Ip詳解卷二》第24章TCP的實現的講解。
應用層的改進TCP並不能感知應用層給了它重複訊息,它只認給它的二進位制資料。就算你重複交給它,它也認為你給了它不同的資料,然後盡職盡責幫你傳送到對方主機。這點需要牢牢記住!
要避免應用層訊息重複,必須還要在應用層做訊息收發確認!
接收方收到訊息後,傳送一個確認訊息(帶上已接收的訊息唯一標記)回去,傳送方標記該訊息已收到;同時接收方也要維護已處理訊息的資訊,如果你維護了這個資訊,即使應用協議實現不正確導致訊息重複收發,至少接收方的邏輯層服務不會再重複處理一次該訊息(如果要展示給使用者更糟糕),最多也就是造成頻寬的浪費。
你可以觀察現有的應用層協議設計,如果有避免訊息重複的應用場合,相應的應用層協議都會設計訊息的唯一標誌,有的類似TCP的遞增序號,有的僅僅保證唯一性。
考慮效能的情況下,最好做批次確認的策略並考慮最大的確認間隔。TCP的滑動視窗實際上就是一個很好的批次確認的參考演算法(尤其是你還需要訊息有序,比如IM訊息展示),你可以在應用程式協議再仿著它的演算法來實現。
如果你的確做了應用層的訊息確認,請檢查實現是否正確!最簡單的追蹤方式就是上面說的記錄日誌。
只要你的確認機制實現正確,不論多糟糕的網路也不會造成重複訊息收發。