UDP傳輸協議

一、傳輸層協議

從之前介紹的網絡層協議來看,通信的兩端是兩臺主機,IP 數據報首部就標明瞭這兩臺主機的 IP 地址。但是從傳輸層來看,是發送方主機中的一個進程與接收方主機中的一個進程在交換數據,因此,嚴格地講,通信雙方不是主機,而是主機中的進程

主機中常常有多個應用進程同時在與外部通信(比如你的瀏覽器和 QQ 在同時運行),下圖中,A 主機的 AP1 進程在與 B 主機的 AP3 進程通信,同時主機 A 的 AP2 進程也在與 B 主機的 AP4 進程通信。

兩個主機的傳輸層之間有一個米黃色雙向箭頭,寫着“運輸層提供應用進程間的邏輯通信”。 邏輯通信:看起來是數據似乎是沿着雙向箭頭在傳輸層水平傳輸的,但實際上是沿圖中的虛線經多個協議層次而傳輸。
這裏寫圖片描述

TCP/IP 協議棧傳輸層有兩個重要協議——UDP 和 TCP,不同的應用進程在傳輸層使用 TCP 或 UDP 之一:
這裏寫圖片描述

二、端口

端口的作用體現在傳輸層。剛纔的圖中,AP1 與 AP3 的通信與 AP2 與 AP4 的通信可以使用同一個傳輸層協議來傳輸(TCP 或 UDP),根據 IP 地址或 MAC 地址都只能是把數據傳到正確的主機,但具體需要傳到哪一個進程,是通過端口來辨認的。比如同時使用瀏覽器和 QQ,瀏覽器佔用 80 端口,而 QQ 佔用 4000 端口,那麼發送過來的 QQ 消息便會通過 4000 端口顯示在 QQ 客戶端,而不會錯誤地顯示在瀏覽器上。

端口號有 0~65535 的編號,其中:

編號 0~1023 爲 系統端口號 ,這些端口號可以在網址 www.iana.org 查詢到,它們被指派給了 TCP/IP 最重要的一些應用程序,以下是一些常見的系統端口號:

應用層協議: FTP TELNET SMTP DNS TFTP HTTP SNMP
系統端口號: 21 23 25 53 69 80 161

編號 1024~49151 爲 登記端口號 ,爲沒有系統端口號的應用程序使用,使用這類端口號必須在 IANA 按規定手續登記,以防止重複。

編號 49152~65535 爲 短暫端口號 ,是留給客戶進程選擇暫時使用的,使用結束後,這類端口號會被放開以供其它程序使用。

三、UDP 概述

UDP(User Datagram Protocol)用戶數據報協議,它只在 IP 數據報服務之上增加了很少一點功能,它的主要特點有:

  1. UDP 是無連接的,發送數據之前不需要建立連接(而 TCP 需要),減少了開銷和時延。

  2. UDP盡最大努力交付,不保證交付可靠性。

  3. UDP 是面向報文的,對於從網絡層交付下來的 IP 數據報,只做很簡單的封裝(8 字節 UDP 報頭),首部開銷小。

  4. UDP 沒有擁塞控制,出現網絡擁塞時發送方也不會降低發送速率。這種特性對某些實時應用是很重要的,比如 IP 電話,視頻會議等,它們允許擁塞時丟失一些數據,因爲如果不拋棄這些數據,極可能造成時延的累積。

  5. UDP 支持一對一、一對多、多對一和多對多的交互通信。

從應用層到傳輸層,再到網絡層的各層次封裝:
這裏寫圖片描述

四、UDP 報文

UDP 數據報可分爲兩部分:UDP 報頭和數據部分。其中數據部分是應用層交付下來的數據。UDP 報頭總共 8 字節,而這 8 字節又分爲 4 個字段:
UDP數據報

  1. 源端口 2 字節 在對方需要回信時可用,不需要時可以全 0;

  2. 目的端口 2 字節 必須,也是最重要的字段;

  3. 長度 2 字節 長度值包括報頭和數據部分;

  4. 校驗和 2 字節 用於檢驗 UDP 數據報在傳輸過程中是否有出錯,有錯就丟棄。

五、tcpdump 抓取 UDP 報文

現在我們動手實踐,嘗試抓取一個 UDP 數據報,並解讀其內容。

我們需要一個小程序,用於向 指定 IP 地址指定端口 發送一個 指定內容 的 UDP 數據報.

#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <sys/types.h>
#include <string.h>

int main(void)
{
        int sockfd;
        struct sockaddr_in server;
        char msg[20]={0};

        sockfd = socket(AF_INET,SOCK_DGRAM,0);
        if (sockfd < 0) {
                perror("socket error!\n");
                exit(-1);
        }

        memset(&server,0,sizeof(server));
        server.sin_family = AF_INET;
        server.sin_addr.s_addr = inet_addr("192.168.1.1");
        server.sin_port = htons(7777);

        strncpy(msg,"hello",sizeof("hello"));

        printf("send message:%s\n",msg);

        if (sendto(sockfd,msg,20,0,(struct sockaddr 
        *)&server,sizeof(server)) != 20) {
                perror("sendto error!\n");
                exit(-1);
        }        

        exit(0);
}

這個 C 程序會向 IP 地址 192.168.1.1 的 7777 端口 發送一條 “hello” 消息。你可以用編輯器修改程序,向不同的 IP 不同的 IP 發送不同的內容。

編譯完成後先別運行,我們還需要使用一個知名的抓包工具 tcpdump ,依次輸入以下命令安裝,並運行 tcpdump:

sudo apt-get update
sudo apt-get install tcpdump
sudo tcpdump -vvv -X udp port 7777

現在最小化當前編譯的終端,另開啓一個終端,輸入以下命令運行剛纔編譯好的 C 程序 test:

這裏寫圖片描述

test 程序運行結束,返回剛纔運行 tcpdump 的終端查看抓包結果:

這裏寫圖片描述

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章