UDP是個什麼鬼

當你的才華不足以知足你的野心時,應該靜下心來努力學習

UDP的概述

  • UDP 是User Datagram Protocol的簡稱, 中文名是用戶數據報協議,是OSI(Open System Interconnection,開放式系統互聯) 參考模型中一種無鏈接的傳輸層協議,提供面向事務的簡單不可靠信息傳送服務,IETF RFC 768是UDP的正式規範。UDP在IP報文的協議號是17。
  • UDP協議全稱是用戶數據報協議,在網絡中它與TCP協議同樣用於處理數據包,是一種無鏈接的協議。在OSI模型中,在第四層——傳輸層,處於IP協議的上一層。UDP有不提供數據包分組、組裝和不能對數據包進行排序的缺點,也就是說,當報文發送以後,是沒法得知其是否安全完整到達的。UDP用來支持那些須要在計算機之間傳輸數據的網絡應用。包括網絡視頻會議系統在內的衆多的客戶/服務器模式的網絡應用都須要使用UDP協議。UDP協議從問世至今已經被使用了不少年,雖然其最初的光彩已經被一些相似協議所掩蓋,可是即便是在今天UDP仍然不失爲一項很是實用和可行的網絡傳輸層協議。

UDP主要特色

  • UDP是一個無鏈接協議,傳輸數據以前源端和終端不創建鏈接,當它想傳送時就簡單地去抓取來自應用程序的數據,並儘量快地把它扔到網絡上。在發送端,UDP傳送數據的速度僅僅是受應用程序生成數據的速度、計算機的能力和傳輸帶寬的限制;在接收端,UDP把每一個消息段放在隊列中,應用程序每次從隊列中讀一個消息段。
  • 因爲傳輸數據不創建鏈接,所以也就不須要維護鏈接狀態,包括收發狀態等,所以一臺服務機可同時向多個客戶機傳輸相同的消息。
  • UDP信息包的標題很短,只有8個字節,相對於TCP的20個字節信息包而言UDP的額外開銷很小。
  • 吞吐量不受擁擠控制算法的調節,只受應用軟件生成數據的速率、傳輸帶寬、源端和終端主機性能的限制。
  • UDP是面向報文的。發送方的UDP對應用程序交下來的報文,在添加首部後就向下交付給IP層。既不拆分,也不合並,而是保留這些報文的邊界,所以,應用程序須要選擇合適的報文大小。

雖然UDP是一個不可靠的協議,但它是分發信息的一個理想協議。例如,在屏幕上報告股票市場、顯示航空信息等等。UDP也用在路由信息協議RIP(Routing Information Protocol)中修改路由表。在這些應用場合下,若是有一個消息丟失,在幾秒以後另外一個新的消息就會替換它。UDP普遍用在多媒體應用中。java

TCP和UDP區別

  • TCP 是面向鏈接的傳輸控制協議,而UDP 提供了無鏈接的數據報服務;
  • TCP 具備高可靠性,確保傳輸數據的正確性,不出現丟失或亂序,而UDP 在傳輸數據前不創建鏈接,不對數據報進行檢查與修改,無須等待對方的應答,因此會出現分組丟失、重複、亂序,應用程序須要負責傳輸可靠性方面的全部工做;
  • UDP 具備較好的實時性,工做效率較 TCP 協議高;
  • UDP 段結構比 TCP 的段結構簡單,所以網絡開銷也小;
  • TCP 協議能夠保證接收端毫無差錯地接收到發送端發出的字節流,爲應用程序提供可靠的通訊服務。對可靠性要求高的通訊系統每每使用 TCP 傳輸數據。

主要應用

適用場合

在選擇UDP做爲傳輸協議時必需要謹慎。在網絡質量使人十分不滿意的環境下,UDP協議數據包丟失會比較嚴重。可是因爲UDP的特性:它不屬於鏈接型協議,於是具備資源消耗小,處理速度快的優勢,因此一般音頻、視頻和普通數據在傳送時使用UDP較多,由於它們即便偶爾丟失一兩個數據包,也不會對接收結果產生太大影響。好比咱們聊天用的ICQ和QQ就是使用的UDP協議。程序員

實際應用

在現場測控領域,面向的是分佈化的控制器、監測器等,其應用場合環境比較惡劣,這樣就對待傳輸數據提出了不一樣的要求,如實時、抗干擾性、安全性等。基於此,現場通訊中,若某一應用要將一組數據傳送給網絡中的另外一個節點,可由UDP進程將數據加上報頭後傳送給IP進程,UDP協議省去了創建鏈接和拆除鏈接的過程,取消了重發檢驗機制,可以達到較高的通訊速率。算法

代碼演示

簡單的一個客戶端/服務端數據收發的例子

UDP客戶端:編程

public class UdpClient {

    public static void main(String[] args) throws IOException {
        //創建一個socket
        DatagramSocket socket = new DatagramSocket();
        //建立一個數據包
        String msg = "你好啊,服務器~";
        InetAddress localhost = InetAddress.getByName("localhost");
        int port = 9090;
        DatagramPacket packet = new DatagramPacket(msg.getBytes(), 0, msg.getBytes().length, localhost, port);
        //發送數據包
        socket.send(packet);
        //關閉流
        socket.close();
    }
}

UDP服務端:安全

public class UdpServer {

    public static void main(String[] args) throws IOException {
        //開啓端口
        DatagramSocket socket = new DatagramSocket(9090);
        //接收數據包
        byte[] bytes = new byte[1024];
        DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length);
        //阻塞接收
        socket.receive(packet);
        String msg = new String(packet.getData(),0,packet.getLength());
        System.out.println("接收到客戶端發來的數據:" + msg);
        //關閉數據流
        socket.close();
    }
}
模擬一個學生和老師的聊天對話
//客戶端
public class TalkSend implements Runnable {

    DatagramSocket socket = null;
    
    BufferedReader br = null;

    private int formPort;
    
    private String toIp;
    
    private int toPort;

    public TalkSend(int formPort, String toIp, int toPort) {
        this.formPort = formPort;
        this.toIp = toIp;
        this.toPort = toPort;
        try {
            socket = new DatagramSocket(this.formPort);
            //準備數據 控制檯讀取System.in
            br = new BufferedReader(new InputStreamReader(System.in));
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    @Override
    public void run() {
        while (true) {
            try {
                String msg = br.readLine();
                byte[] bytes = msg.getBytes();
                DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length, new InetSocketAddress(this.toIp, this.toPort));
                //發送數據
                socket.send(packet);
                if (msg.equals("bye")) {
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        socket.close();
    }
}
//服務端
public class TalkReceive implements Runnable {

    DatagramSocket socket = null;

    private int port;

    private String msgForm;

    public TalkReceive(int port, String msgForm) {
        this.port = port;
        this.msgForm = msgForm;
        try {
            socket = new DatagramSocket(port);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }


    @Override
    public void run() {
        while (true) {
            try {
                //準備接收包裹
                byte[] bytes = new byte[1024];
                DatagramPacket packet = new DatagramPacket(bytes, 0, bytes.length);
                socket.receive(packet);
                //斷開鏈接 bye
                String msg = new String(packet.getData(), 0, packet.getLength());
                System.out.println(msgForm + ":" + msg);
                if ("bye".equals(msg)) {
                    break;
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        socket.close();
    }
}
public class TalkStudent {
    public static void main(String[] args) {
        new Thread(new TalkSend(7777,"localhost",8888)).start();
        new Thread(new TalkReceive(9999,"老師")).start();
    }
}
public class TalkTeacher {
    public static void main(String[] args) {
        new Thread(new TalkSend(5555,"localhost",9999)).start();
        new Thread(new TalkReceive(8888,"學生")).start();
    }
}

測試一下,結果以下:服務器

image-20210420140845047.png

image-20210420140915126.png

總結

  • UDP用戶數據報協議,是面向無鏈接的通信協議,UDP數據包括目的端口號和源端口號信息,因爲通信不須要鏈接,因此能夠實現廣播發送。
  • UDP通信時不須要接收方確認,屬於不可靠的傳輸,可能會出現丟包現象,實際應用中要求程序員編程驗證。
相關文章
相關標籤/搜索