1. 程式人生 > >udp用戶數據報協議

udp用戶數據報協議

sys 個數 out 進制 包括 影響 final 參考 網際協議

  UDP 是User Datagram Protocol的簡稱, 中文名是用戶數據報協議,是OSI(Open System Interconnection,開放式系統互聯) 參考模型中一種無連接的傳輸層協議,提供面向事務的簡單不可靠信息傳送服務,IETF RFC 768是UDP的正式規範。UDP在IP報文的協議號是17。

  UDP協議全稱是用戶數據報協議[1] ,在網絡中它與TCP協議一樣用於處理數據包,是一種無連接的協議。在OSI模型中,在第四層——傳輸層,處於IP協議的上一層。UDP有不提供數據包分組、組裝和不能對數據包進行排序的缺點,也就是說,當報文發送之後,是無法得知其是否安全完整到達的。UDP用來支持那些需要在計算機之間傳輸數據的網絡應用。包括網絡視頻會議系統在內的眾多的客戶/服務器模式的網絡應用都需要使用UDP協議。UDP協議從問世至今已經被使用了很多年,雖然其最初的光彩已經被一些類似協議所掩蓋,但是即使是在今天UDP仍然不失為一項非常實用和可行的網絡傳輸層協議。   與所熟知的TCP(傳輸控制協議)協議一樣,UDP協議直接位於IP(網際協議)協議的頂層。根據OSI(開放系統互連)參考模型,UDP和TCP都屬於傳輸層協議。UDP協議的主要作用是將網絡數據流量壓縮成數據包的形式。一個典型的數據包就是一個二進制數據的傳輸單位。每一個數據包的前8個字節用來包含報頭信息,剩余字節則用來包含具體的傳輸數據。   選擇UDP必須要謹慎。在網絡質量令人十分不滿意的環境下,UDP協議數據包丟失會比較嚴重。但是由於UDP的特性:它不屬於連接型協議,因而具有資源消耗小,處理速度快的優點,所以通常音頻、視頻和普通數據在傳送時使用UDP較多,因為它們即使偶爾丟失一兩個數據包,也不會對接收結果產生太大影響。比如我們聊天用的ICQ和QQ就是使用的UDP協議。   每個UDP報文分UDP報頭和UDP數據區兩部分。報頭由四個16位長(4個域組成,其中每個域各占用2個字節)字段組成,分別說明該報文的源端口、目的端口、報文長度以及校驗值。 服務端
import
java.io.IOException; import java.net.DatagramPacket; import java.net.DatagramSocket; public class UdpServer { public static void main(String[] args)throws IOException{ String str_send = "Hello UDPclient"; byte[] buf = new byte[1024]; //服務端在3000端口監聽接收到的數據 DatagramSocket ds = new
DatagramSocket(3000); //接收從客戶端發送過來的數據 DatagramPacket dp_receive = new DatagramPacket(buf, 1024); System.out.println("server is on,waiting for client to send data......"); boolean f = true; while(f){ //服務器端接收來自客戶端的數據 ds.receive(dp_receive); System.out.println(
"server received data from client:"); String str_receive = new String(dp_receive.getData(),0,dp_receive.getLength()) + " from " + dp_receive.getAddress().getHostAddress() + ":" + dp_receive.getPort(); System.out.println(str_receive); //數據發動到客戶端的3000端口 DatagramPacket dp_send= new DatagramPacket(str_send.getBytes(),str_send.length(),dp_receive.getAddress(),9000); ds.send(dp_send); //由於dp_receive在接收了數據之後,其內部消息長度值會變為實際接收的消息的字節數, //所以這裏要將dp_receive的內部消息長度重新置為1024 dp_receive.setLength(1024); } ds.close(); } }

客戶端

import java.io.IOException;
import java.io.InterruptedIOException;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;

public class UdpClient {
    private static final int TIMEOUT = 5000;  //設置接收數據的超時時間  
    private static final int MAXNUM = 5;      //設置重發數據的最多次數  
    public static void main(String args[])throws IOException{  
        String str_send = "Hello UDPserver";  
        byte[] buf = new byte[1024];  
        //客戶端在9000端口監聽接收到的數據  
        DatagramSocket ds = new DatagramSocket(9000);  
        InetAddress loc = InetAddress.getLocalHost();  
        //定義用來發送數據的DatagramPacket實例  
        DatagramPacket dp_send= new DatagramPacket(str_send.getBytes(),str_send.length(),loc,3000);  
        //定義用來接收數據的DatagramPacket實例  
        DatagramPacket dp_receive = new DatagramPacket(buf, 1024);  
        //數據發向本地3000端口  
        ds.setSoTimeout(TIMEOUT);              //設置接收數據時阻塞的最長時間  
        int tries = 0;                         //重發數據的次數  
        boolean receivedResponse = false;     //是否接收到數據的標誌位  
        //直到接收到數據,或者重發次數達到預定值,則退出循環  
        while(!receivedResponse && tries<MAXNUM){  
            //發送數據  
            ds.send(dp_send);  
            try{  
                //接收從服務端發送回來的數據  
                ds.receive(dp_receive);  
                //如果接收到的數據不是來自目標地址,則拋出異常  
                if(!dp_receive.getAddress().equals(loc)){  
                    throw new IOException("Received packet from an umknown source");  
                }  
                //如果接收到數據。則將receivedResponse標誌位改為true,從而退出循環  
                receivedResponse = true;  
            }catch(InterruptedIOException e){  
                //如果接收數據時阻塞超時,重發並減少一次重發的次數  
                tries += 1;  
                System.out.println("Time out," + (MAXNUM - tries) + " more tries..." );  
            }  
        }  
        if(receivedResponse){  
            //如果收到數據,則打印出來  
            System.out.println("client received data from server:");  
            String str_receive = new String(dp_receive.getData(),0,dp_receive.getLength()) +   
                    " from " + dp_receive.getAddress().getHostAddress() + ":" + dp_receive.getPort();  
            System.out.println(str_receive);  
            //由於dp_receive在接收了數據之後,其內部消息長度值會變為實際接收的消息的字節數,  
            //所以這裏要將dp_receive的內部消息長度重新置為1024  
            dp_receive.setLength(1024);     
        }else{  
            //如果重發MAXNUM次數據後,仍未獲得服務器發送回來的數據,則打印如下信息  
            System.out.println("No response -- give up.");  
        }  
        ds.close();  
    }
}

  

udp用戶數據報協議