最近在做一個項目,在這之前,做了個驗證程序.
發現客戶端連續發來1000個1024字節的包,服務器端出現了丟包現象.
糾其原因,是服務端在還未完全處理掉數據,客戶端已經數據發送完畢且關閉了.
我用過sleep(10),暫時解決這個問題,但是這不是根本解決辦法,如果數據量大而多,網絡情況不太好的話,還是有可能丟失.
你試着用阻塞模式吧...
select...我開始的時候好像也遇到過..不過改為阻塞模式后就沒這個問題了...
采用回包機制,每個發包必須收到回包后再發下一個
UDP丟包是正常現象,因為它是不安全的。
丟包的原因我想並不是“服務端在還未完全處理掉數據,客戶端已經數據發送完畢且關閉了”,而是服務器端的socket接收緩存滿了(udp沒有流量控制,因此發送速度比接收速度快,很容易出現這種情況),然后系統就會將后來收到的包丟棄。你可以嘗試用setsockopt()將接收緩存(SO_RCVBUF)加大看看能不能解決問題。
服務端采用多線程pthread接包處理
UDP是無連接的,面向消息的數據傳輸協議,與TCP相比,有兩個致命的缺點,一是數據包容易丟失,二是數據包無序。
要實現文件的可靠傳輸,就必須在上層對數據丟包和亂序作特殊處理,必須要有要有丟包重發機制和超時機制。
常見的可靠傳輸算法有模擬TCP協議,重發請求(ARQ)協議,它又可分為連續ARQ協議、選擇重發ARQ協議、滑動窗口協議等等。
如果只是小規模程序,也可以自己實現丟包處理,原理基本上就是給文件分塊,每個數據包的頭部添加一個唯一標識序號的ID值,當接收的包頭部ID不是期望中的ID號,則判定丟包,將丟包ID發回服務端,服務器端接到丟包響應則重發丟失的數據包。
模擬TCP協議也相對簡單,3次握手的思想對丟包處理很有幫助。
udp是不安全的,如果不加任何控制,不僅會丟失包,還可能收到包的順序和發送包的順序不一樣。這個必須在自己程序中加以控制才行。
收到包后,要返回一個應答,如果發送端在一定時間內沒有收到應答,則要重發。
UDP本來存在丟包現象,現在的解決方案暫時考慮雙方增加握手.
這樣做起來,就是UDP協議里面加上了TCP的實現方法.
程序中采用的是pthread處理,丟包率時大時小,不穩定可靠
我感覺原因可能有兩個,一個是客戶端發送過快,網絡狀況不好或者超過服務器接收速度,就會丟包。
第二個原因是服務器收到包后,還要進行一些處理,而這段時間客戶端發送的包沒有去收,造成丟包。
解決方法,
一是 客戶端降低發送速度,可以等待回包,或者加一些延遲。
二是,服務器部分單獨開一個線程,去接收UDP數據,存放在一個緩沖區中,又另外的線程去處理收到的數據,盡量減少因為處理數據延時造成的丟包。
有兩種方法解決樓主的問題:
方法一:重新設計一下協議,增加接收確認超時重發。(推薦)
方法二:在接收方,將通信和處理分開,增加個應用緩沖區;如果有需要增加接收socket的系統緩沖區。(本方法不能從根本解決問題,只能改善)
網絡丟包,是再正常不過的了。
既然用UDP,就要接受丟包的現實,否則請用TCP。
如果必須使用UDP,而且丟包又是不能接受的,只好自己實現確認和重傳,說白了,就是自己實現TCP(當然是部分和有限的簡單實現)。
UDP是而向無連接的,用戶在實施UDP編程時,必須制定上層的協議,包括流控制,簡單的超時和重傳機制,如果不要求是實時數據,我想TCP可能會更適合你!
- huangcanbao 發表於Tuesday, September 22, 2009 7:33:22 PM 舉報
- 今天接到了電話面試,還好我的解決方案和你這位朋友的一樣。1:給自己發的數據定義協議,序號 大小 數據。 2:傳輸過程都要進行雙方驗證,是否接受到正確的數據。根據傳輸的字節大小來管理的。
- 轉自 http://blog.csdn.net/yylklshmyt20090217/archive/2009/06/17/4275937.aspx
- 建議的辦法是,對於大的報文自己進行一個分包和組包操作.要減少丟包率(丟包重發,同樣是不小的消耗),把單包的大小定在1500字節以內,按24MBit/s的帶寬最大流通量2048個包每秒,這個壓力是相當小的.
- 丟包是很正常的,發包越大丟包的可能性就越高,與網卡速度沒有必然聯系,需要自己設計應答和重發機制。至於多大的數據包最合適,要在實際運行的環境中測試才能知道。程序運行過程中可以自己統計並計算丟包率,然后動態調整數據包的大小來適應運行環境。
-
另外是內存池這些,最簡單的,你要是每次new char[1024]再去收,那收線程速度就當下來了.
記住,收線程不要做任何事.那怕只查個MAP,在上萬包每秒時,每秒的操作就上萬個MAP查詢,
另外丟包可能是發送端,發出來已經丟了,你要考慮發送的的發送處理,發送處理寫得不好,其實發
的過程根本沒機會出網卡緩沖,就已經丟了有可能.
中間路由器環節(這個無法控制,只能看看這個環節性能如何)
