UDP踩坑——爲啥老阻塞?

衆所周知,UDP是盡力而爲的服務,也就是傳輸是不可靠的,丟包不會給你重傳,只會作一些簡單的查錯。最最最重要的是UDP沒有TCP的三次握手機制!若是你們想要經過UDP傳輸一些文件之類的話,就須要模擬TCP三次握手,讓UDP可以「活」起來,否則就會形成丟包,或者形成由於丟包而產生的阻塞。spa

  1. 踩坑①:server


    image
    圖中左側的流程中,Client端按照文件大小除以packet大小來肯定while循環的次數,這是比較致命的,由於在UDP中極有可能出現丟包的狀況,那麼循環的次數就不是正確的次數了,從而形成阻塞。而丟包在以太網中仍是比較少見的,可是仍是發生了丟包,這是爲何呢?八成就是在在Socket創建以前就丟了!因此進而形成循環次數不對,Client苦苦等待,Server端已經發完運行以後的程序了。blog

    那麼咱們應該如何解決這樣的問題呢?get

    • 不用循環次數來退出while循環!而用自定的一種說明,好比Server端傳完數據以後再額外發一個終止信息,Client接收到終止信息以後退出while循環,那麼這樣依舊可能形成終止信號丟失,Client又阻塞了...這時一個辦法是採用可靠傳輸的TCP傳送終止信號,或者經過setSoTimeout來設置超時時間,一旦超過這個時間就退出。
    • 讓Server端等待Client創建Socket,創建完以後再給爺傳!也是採用可靠的數據傳輸TCP,告知Server我已經創建鏈接了,您能夠傳輸了。也就是圖中右側部分的流程。
    • 圖中還有第三種解決方法就是直接讓Server端sleep,可是由於時間不太好肯定,因此不太推薦。
  2. 踩坑②:

    在server端,咱們建立固定大小(如512B)的byte[] b封裝咱們的dataPacket,可是文件每每不是能被完整劃分的,因此最後一個文件的實際信息大小可能會小於512B。此時在Client,咱們將傳輸以後的文件寫進本地的文件中,dp是dataPacket,裏面存儲着傳輸過來的信息byte[] b =dp.getData(),在將b寫入文件時,咱們應該取0-b的實際有效信息的長度,否則會產生實際有效信息長度小於512B時,b會被自動填充前面一個dp的信息以使得b的大小達到512,這就產生了冗餘it

    具體結果以下:class

    正確接收文件:循環

    image
    產生冗餘以後的:程序

    image
    能夠明顯看到重複的文字,因此我猜想dataPacket是排隊連起來的,若信息長度不夠時,會拿前面一個數據包信息填充。方法

相關文章
相關標籤/搜索