正兒八經的後台開發幹了好多年, 可是對於網路的理解還是僅僅停留在應用層層面, 比如http,應用層下面的tcp/udp知之甚淺,更別提IP、數據鏈路相關的內容了。

網路知識比較難懂, 主要是離平時工作實踐甚遠,比如說普通的網路程序開發,用http足以滿足需求,http滿足不了的情況就用socket,socket在http之下,屬於傳輸層,算是與tcp直接相關, 可是使用socket只需調用編程語言提供的類庫即可,根本用不著去了解tcp中的細節,所以對於理解tcp還是沒有跨越性的幫助。網路理論書籍上描述的三次握手、傳輸窗口、確認重傳等等概念還是讓人摸不著頭腦。

本來以為職業生涯對於網路原理的理解也就到此為止了,然而還是有所突破了。

因為一個需求,需要將伺服器上一些數據傳輸到自己的工作電腦上,突發奇想要自己實現傳輸功能,而不是部署個http伺服器。既然不使用http, 那麼使用tcp是最合適的,實現一個java tcp server和一個javafx tcp客戶端。這種方案省事但太千遍一律,還不如直接部署一個 http server,因此我決定用udp完成這個任務,開發一個udp server和java udp客戶端。

因為對udp的不熟悉,實現過程中碰到了不少問題,對印證和理解tcp起到不少幫助。

比如說使用udp向目標發送一個數據包需要得到對方的一個確認消息才算完成,否則怎麼知道目標已經收到了我發送過去的消息呢, udp本身並不保證消息必然送達至目標,所以必須設計一種消息確認機制。簡單的做法是為每份發送的數據包指定一個消息頭,頭裡面有一個消息編號,通過消息編號來實現消息接收成功確認。tcp則自帶這個功能。

比如說操作系統調用規定,每個udp數據包大小不得超出64KB,其中包含udp/ip的包頭信息。那麼當需要傳輸超出這個大小的數據時勢必需要將數據分片傳輸,而另一端還需要將接受到的數據重組,此外udp不保證每個數據包的到達順序,所以還需要對接收到的數據進行排序, 甚至於什麼時候進行排序重組也需要一個通知,因為如果不這麼做目標根本沒有辦法知道對方已經發送了所有需要發送的數據。tcp則自帶這個功能,而且有非常完善的實現機制,使用tcp你只要執行傳送命令, 而不用管怎麼傳,udp則不行。

比如通過udp傳輸的消息會丟失,所以我們需要一種確認機制, 未得到確認的包則需要重傳, 可是確認包丟失了又該怎麼辦?每次傳輸數據包的大小應該是多少?超時重傳的時間應該是多久?這些我並未在我的程序中實現完善的解決方案。tcp則自帶這個功能。

總而言之,使用udp編程比使用tcp複雜很多,從實際的工作出發,能使用tcp就不要使用udp,使用tcp能使工作更輕鬆,同時也能使程序更可靠,不過通常而言tcp幾乎可以應用於所有網路編程的場景,除了一些極為特殊的情況外,比如說實時遊戲畫面同步。除此之外它的最大作用應該是協助理解tcp吧。

我寫的程序大概長這樣,客戶端部分, 服務端就是一個普通的進程

推薦閱讀:

相关文章