Android與物聯網設備通訊-UDP&TCP協議

有不少小夥伴私聊我說更新太慢,奪命吹吹吹。一週一次,還不能知足大家嗎?html

好,那我不寫了。╭(╯^╰)╮!!!java

額,儘可能保持完成審覈後就交貨發佈啦。實際上前面的章節都是週末完成等到週三才發的。編程

上一節咱們細說了網絡模型分層。知道了七層分法實際如今只有五層了。今天咱們展開來學習傳輸層UDP和TCP的協議。由於這兩個協議關聯性比較大,且篇幅不高。故合併層一個小節學習。緩存

章節

目錄

  • UDP
  • TCP

UDP (User Datagram Protocol)

它是一種高速但數據不可靠的協議,爲何說它不可靠呢?是由於與之對應的TCP是很是可靠和穩定的。咱們先看一下UDP的報文結構再講解傳遞數據過程的原理。安全

UDP報文

image.png

能夠看到很簡單,沒有什麼東西須要特別說明的,根據前幾節的知識就能夠推斷出來。UDP的效率高並不是在報文上,而是它的傳輸機制就是隻管往外發,對方能不能接收到(是否存在),並不關心。服務器

你必定還記得網絡不通的時候ping一下,這種小秀的騷操做的把?沒有錯它的底層就是依靠UDP協議直接實現的,ping的過程就是客戶端組裝UDP報文,和DNS服務器接收解析UDP並響應客戶端的過程。當ping不通的時候就會出現超時,即DNS服務器不回覆客戶端。網絡

因此UDP的傳輸可理解成來數據了,就無論三七二一就是一個走你,拜拜了您勒。也不去校驗到底有沒有收到。socket

正常狀況下一條報文會被路由、交換機通過一層層轉發,最後到該接收的位置。他們依靠上一節提到的數據鏈路層和網絡層來尋找主機。UDP協議只關心端口。這種最典型的UDP稱爲單播UDP,除此以外還有組播廣播。關於組播和廣播,咱們後續的章節講到作查找設備時會詳細講解,並作一個小demo。工具

TCP(Transmission Control Protocol)

相對UDP來講TCP協議就要穩定不少了。一樣咱們先看報文結構,再學習傳輸原理。學習

TCP報文

image.png

咱們重點看幾個字段說明:

  • 序號: 表示發送端當前包位於整組數據的第幾個字節,也叫流水號。用於確保數據組的穩定性。

  • ack號: 也叫確認號,表示接收方收到了多少個字節,表示期待下一組數據的字節序號。

  • 數據偏移: 通常不用,可是出如今TCP頭裏若是可選字段增長後,就要在數據偏移中指明偏移的位置,最多能夠將20字節的頭擴展到60個字節。

  • 控制位: 6個標誌位URG ACK PSH RST SYN FIN每個表示一個控制功能,也就是告訴對方當前的包是作什麼用的標識。

  • 窗口: 接收端告訴發送端自身的緩存大小的。避免過大的數據包致使接收端接受不過來而丟失數據。

控制位詳解

  • URG: 緊急指針標誌是否有效。

  • ACK: 確認序號是否有效。

  • PSH: 刷新緩存標誌1有效,0忽略,要求把數據儘快給應用,而不要放在緩存裏。(java裏的flush方法)

  • RST: 異常標誌,表示強制斷開鏈接,在異常的狀況下。

  • SYN: 鏈接過程同步序號標誌。

  • FIN: finish標誌,用於釋放鏈接1表示關閉鏈接。

咋一看你會發現TCP的報文比UDP複雜了好多,一大堆東西。個人老夥計,別擔憂。那麼底層的事情又不要你處理。你只須要知道它們在幹嗎。而且值得說的是在Java上作socket編程時,你根本就感知不到底層字段的狀態。到上層在處理數據的時候僅僅只有一個輸入流和輸出流了。這樣極大的方便了應用層的簡便開發。

TCP協議分析

咱們知道TCP是面向鏈接的,它嚴格的把控住了每一次傳輸的數據的穩定性。那麼它是如何作到的呢?乾巴巴的說太過於抽象,如今咱們實際動手寫一下代碼(kotlin)搭配利刃wireshark分析一下。

服務端

fun main(args: Array<String>) {
  val ss=  ServerSocket(22222);
    while (true){
        val accept = ss.accept()
        val dataInputStream = DataInputStream(accept.getInputStream())
        val dataOutputStream = DataOutputStream(accept.getOutputStream())
        val s = dataInputStream.readUTF()
        dataOutputStream.writeUTF("hello Server")
        dataInputStream.close()
        dataOutputStream.close()
        accept.close()
        println(s)
    }
}
複製代碼

客戶端

fun main(args: Array<String>) {
    val socket = Socket("192.168.0.5", 22222);
    val dataOutputStream = DataOutputStream(socket.getOutputStream())
    val dataInputStream = DataInputStream(socket.getInputStream())
    dataOutputStream.writeUTF("hello")
    val s = dataInputStream.readUTF()
    dataInputStream.close()
    dataOutputStream.close()
    socket.close()
    println(s)
}
複製代碼

值得注意的是wireshark沒法直接抓到TCP在本地的迴路包,可是咱們可使用命令行配置一下就能夠了,否則抓不到本機的迴路包。

  • 給路由表添加一條 route add 本機IP mask 255.255.255.255 路由IP metric 1

  • 抓完刪除route delete 本機IP

爲了方便演示,我這裏使用了兩塊網卡。因此往路由裏添加了兩次迴路IP。

這裏首先咱們開啓服務端,進入了循環監聽狀態,隨後開啓了客戶端鏈接上後發送一個hello,服務端收到後回覆了一個hello Server。再沒有作更多的事情了。咱們來看一下經過wireshark抓到的包。

image.png

  • 客戶端: 192.168.0.4端口:55705(操做系統協議棧分配)
  • 服務端: 192.168.0.5 端口:22222(咱們定義的)

1.啓動服務端後,操做系統將開始對22222端口的SYN包進行監聽。

2.客戶端啓動,並嘗試鏈接服務端,由操做系統協議棧隨機分配一個發送端口。

握手:

3.客戶端組裝一組SYN報文發送至服務端22222號端,標記客戶端seq0(完成第一次握手)

4.服務端收到SYN包,並組裝一組SYN、ACK報文,內容是告訴客戶端我確認了你的SYN包,並期待你的下一組數據從1開始,標記服務端seq0(完成第二次握手)

5.客戶端收到服務端返回的SYN、ACK包報文,,標記客戶端seq1,並組裝一組ACK報文,內容是告訴服務端指望收到的下一組ack1開始。(完成第三次握手)

發包:

6.客戶端組裝了一組PSH、ACK包,並帶上ack=1,內容爲hello,發送個服務端。

7.服務端收到了內容爲hello的包,確認後將ack加上收到的內容的長度。組裝一組PSH、ACK並帶上ack=8發送給客戶端。

揮手:

8.客戶端收到服務端的消息,更新本身的seq=8,並組裝一組FIN、ACK包,並帶上ack=15確認號,嘗試請求斷開鏈接。(客戶端第一次主動揮手)

9.服務端收到客戶端的FIN包,更新本身的seq=15,並組裝一組FIN、ACK包,並帶上ack=8發送給客戶端。(服務端確認,開始第二次揮手。)

10.客戶端收到服務端的ack包並檢測seq是否一致,組裝一組ACK包發送給服務端。(第三次揮手)

11.服務端收到客戶端的ack並檢測seq是否一致,組裝一組ACK包發送給客戶端。(第四次揮手)

上面描述的這個過程從字面上去看並無太大意義,我但願你真正打開wireshark和代碼,調試着玩玩。

回顧過程:

握手: 客戶端和服務端會先進行三次握手,握手的時候會告訴對方自身的窗體大小和ack確認號。這個過包的功能是從ACK、SYN來達到認識的。

傳輸數據: 在接受對方的數據時,在下一組包裏帶上ACK標記告知對方我已經收到了多少內容,期待下一組內容的起始位置。

揮手: 相互確認包是否發送完整,再雙方確認了ACK後。才真正揮手完畢。

丟包或包校驗不對狀況: 操做系統協議棧會根據ACKSEQ號對控制位爲ACK的包進行校驗,若是對不上則要求重發上一組包。


到此UDP&TCP的協議咱們就學習完了。這裏沒有去演示UDP包的抓取過程,由於若是TCP都會了UDP就不是什麼難題。再一個沒有展現wireshark的具體使用過程,由於網上實在有不少優秀的教程了。

即使如此,我敢打賭的是若是讀者是第一次接觸TCP/IP絕對會由於不少概念和發來發去的字段搞得頭暈或者只知其一;不知其二。由於個人能力還不足以讓你看看文章就徹底懂了。(原話出自凱哥 ^o^

聽我一句勸,這個時候不要放棄,成熱打鐵趕快打開分析工具,照着我前面的代碼跑起來。再拿出紙筆寫寫畫一畫。深挖一下真正的去感覺它們的巧妙之處。你會感受這個設計是很是棒的。

話說你們看得真的有收穫嗎?若是以爲不錯,又想獎勵我一下戳這裏打賞(據說打賞有吹更效果噢)。

相關文章
相關標籤/搜索