posts - 297,  comments - 1618,  trackbacks - 0
          一. UDP協議定義
             UDP協議的全稱是用戶數據報,在網絡中它與TCP協議一樣用于處理數據包。在OSI模型中,在第四層——傳輸層,處于IP協議的上一層。UDP有不提供數據報分組、組裝和不能對數據包的排序的缺點,也就是說,當報文發送之后,是無法得知其是否安全完整到達的。

          二. 使用UDP的原因
             它不屬于連接型協議,因而具有資源消耗小,處理速度快的優點,所以通常音頻、視頻和普通數據在傳送時使用UDP較多,因為它們即使偶爾丟失一兩個數據包,也不會對接收結果產生太大影響。比如我們聊天用的ICQ和OICQ就是使用的UDP協議。在選擇使用協議的時候,選擇UDP必須要謹慎。在網絡質量令人不十分滿意的環境下,UDP協議數據包丟失會比較嚴重。

          三. 在Java中使用UDP協議編程的相關類
          1. InetAddress
              用于描述和包裝一個Internet IP地址。有如下方法返回實例:
              getLocalhost():返回封裝本地地址的實例。

           getAllByName(String host):返回封裝Host地址的InetAddress實例數組。

           getByName(String host):返回一個封裝Host地址的實例。其中,Host可以是域名或者是一個合法的IP地址。
              InetAddress.getByAddress(addr):根據地址串返回InetAddress實例。
              InetAddress.getByAddress(host, addr):根據主機地符串和地址串返回InetAddress實例。

          2. DatagramSocket
              用于接收和發送UDP的Socket實例。該類有3個構造函數:
              DatagramSocket():通常用于客戶端編程,它并沒有特定監聽的端口,僅僅使用一個臨時的。程序會讓操作系統分配一個可用的端口。
              DatagramSocket(int port):創建實例,并固定監聽Port端口的報文。通常用于服務端

           DatagramSocket(int port, InetAddress localAddr):這是個非常有用的構建器,當一臺機器擁有多于一個IP地址的時候,由它創建的實例僅僅接收來自LocalAddr的報文。
              DatagramSocket具有的主要方法如下:
              1)receive(DatagramPacket d):接收數據報文到d中。receive方法產生一個“阻塞”。“阻塞”是一個專業名詞,它會產生一個內部循環,使程序暫停在這個地方,直到一個條件觸發。

           2)send(DatagramPacket dp):發送報文dp到目的地。

           3)setSoTimeout(int timeout):設置超時時間,單位為毫秒。

           4)close():關閉DatagramSocket。在應用程序退出的時候,通常會主動釋放資源,關閉Socket,但是由于異常地退出可能造成資源無法回收。所以,應該在程序完成時,主動使用此方法關閉Socket,或在捕獲到異常拋出后關閉Socket。

          3. DatagramPacket
              用于處理報文,它將Byte數組、目標地址、目標端口等數據包裝成報文或者將報文拆卸成Byte數組。應用程序在產生數據包是應該注意,TCP/IP規定數據報文大小最多包含65507個,通常主機接收548個字節,但大多數平臺能夠支持8192字節大小的報文。DatagramPacket類的構建器共有4個:
              DatagramPacket(byte[] buf, int length):將數據包中Length長的數據裝進Buf數組,一般用來接收客戶端發送的數據。
              DatagramPacket(byte[] buf, int offset, int length):將數據包中從Offset開始、Length長的數據裝進Buf數組。
              DatagramPacket(byte[] buf, int length, InetAddress clientAddress, int clientPort):從Buf數組中,取出Length長的數據創建數據包對象,目標是clientAddress地址,clientPort端口,通常用來發送數據給客戶端。

           DatagramPacket(byte[] buf, int offset, int length, InetAddress clientAddress, int clientPort):從Buf數組中,取出Offset開始的、Length長的數據創建數據包對象,目標是clientAddress地址,clientPort端口,通常用來發送數據給客戶端。
              主要的方法如下:
               1)getData(): 從實例中取得報文的Byte數組編碼。
               2)setDate(byte[]  buf):將byte數組放入要發送的報文中。

          四. 實例解析
              下面讓我們來看一個UDP的服務端和客戶端交互通信的例子,在本例中,服務端循環等待客戶端發送的信息,并對其進行回應,客戶端向服務端發送信息,并接收服務端的回應信息。代碼如下:
              1. UDP的服務端程序

          import java.io.IOException;
          import java.net.DatagramPacket;
          import java.net.DatagramSocket;
          import java.net.InetAddress;
          import java.net.InetSocketAddress;
          import java.net.SocketException;

          /**
           * Copyright 2007 GuangZhou Cotel Co. Ltd.
           * All right reserved.    
           * UTP服務類.     
           * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
           * 
          @version 1.0 
           * Creation date: 2007-8-16 - 下午10:32:31
           
          */

          public class UdpServerSocket {
              
          private byte[] buffer = new byte[1024];
              
              
          private DatagramSocket ds = null;

              
          private DatagramPacket packet = null;

              
          private InetSocketAddress socketAddress = null;

              
          private String orgIp;

              
          /**
               * 構造函數,綁定主機和端口.
               * 
          @param host 主機
               * 
          @param port 端口
               * 
          @throws Exception
               
          */

              
          public UdpServerSocket(String host, int port) throws Exception {
                  socketAddress 
          = new InetSocketAddress(host, port);
                  ds 
          = new DatagramSocket(socketAddress);
                  System.out.println(
          "服務端啟動!");
              }

              
              
          public final String getOrgIp() {
                  
          return orgIp;
              }


              
          /**
               * 設置超時時間,該方法必須在bind方法之后使用.
               * 
          @param timeout 超時時間
               * 
          @throws Exception
               
          */

              
          public final void setSoTimeout(int timeout) throws Exception {
                  ds.setSoTimeout(timeout);
              }


              
          /**
               * 獲得超時時間.
               * 
          @return 返回超時時間.
               * 
          @throws Exception
               * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
               * Creation date: 2007-8-16 - 下午10:34:36
               
          */

              
          public final int getSoTimeout() throws Exception {
                  
          return ds.getSoTimeout();
              }


              
          /**
               * 綁定監聽地址和端口.
               * 
          @param host 主機IP
               * 
          @param port 端口
               * 
          @throws SocketException
               * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
               * Creation date: 2007-8-16 - 下午10:36:17
               
          */

              
          public final void bind(String host, int port) throws SocketException {
                  socketAddress 
          = new InetSocketAddress(host, port);
                  ds 
          = new DatagramSocket(socketAddress);
              }



              
          /**
               * 接收數據包,該方法會造成線程阻塞.
               * 
          @return 返回接收的數據串信息
               * 
          @throws IOException
               * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
               * Creation date: 2007-8-16 - 下午10:38:24
               
          */

              
          public final String receive() throws IOException {
                  packet 
          = new DatagramPacket(buffer, buffer.length);
                  ds.receive(packet);
                  orgIp 
          = packet.getAddress().getHostAddress();
                  String info 
          = new String(packet.getData(), 0, packet.getLength());
                  System.out.println(
          "接收信息:" + info);
                  
          return info;
              }


              
          /**
               * 將響應包發送給請求端.
               * 
          @param bytes 回應報文
               * 
          @throws IOException
               * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
               * Creation date: 2007-8-16 - 下午11:05:31
               
          */

              
          public final void response(String info) throws IOException {
                  System.out.println(
          "客戶端地址 : " + packet.getAddress().getHostAddress()
                          
          + ",端口:" + packet.getPort());
                  DatagramPacket dp 
          = new DatagramPacket(buffer, buffer.length, packet
                          .getAddress(), packet.getPort());
                  dp.setData(info.getBytes());
                  ds.send(dp);
              }


              
          /**
               * 設置報文的緩沖長度.
               * 
          @param bufsize 緩沖長度
               * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
               * Creation date: 2007-8-16 - 下午10:47:49
               
          */

              
          public final void setLength(int bufsize) {
                  packet.setLength(bufsize);
              }


              
          /**
               * 獲得發送回應的IP地址.
               * 
          @return 返回回應的IP地址
               * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
               * Creation date: 2007-8-16 - 下午10:48:27
               
          */

              
          public final InetAddress getResponseAddress() {
                  
          return packet.getAddress();
              }


              
          /**
               * 獲得回應的主機的端口.
               * 
          @return 返回回應的主機的端口.
               * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
               * Creation date: 2007-8-16 - 下午10:48:56
               
          */

              
          public final int getResponsePort() {
                  
          return packet.getPort();
              }


              
          /**
               * 關閉udp監聽口.
               * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
               * Creation date: 2007-8-16 - 下午10:49:23
               
          */

              
          public final void close() {
                  
          try {
                      ds.close();
                  }
           catch (Exception ex) {
                      ex.printStackTrace();
                  }

              }


              
          /**
               * 測試方法.
               * 
          @param args
               * 
          @throws Exception
               * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
               * Creation date: 2007-8-16 - 下午10:49:50
               
          */

              
          public static void main(String[] args) throws Exception {
                  String serverHost 
          = "127.0.0.1";
                  
          int serverPort = 3344;
                  UdpServerSocket udpServerSocket 
          = new UdpServerSocket(serverHost, serverPort);
                  
          while (true{
                      udpServerSocket.receive();
                      udpServerSocket.response(
          "你好,sterning!");
                      
                  }

              }

          }

             2. UDP客戶端程序

          import java.io.*;
          import java.net.*;

          /**
           * Copyright 2007 GuangZhou Cotel Co. Ltd.
           * All right reserved.    
           * UDP客戶端程序,用于對服務端發送數據,并接收服務端的回應信息.
           * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
           * 
          @version 1.0 
           * Creation date: 2007-8-16 - 下午10:54:23
           
          */

          public class UdpClientSocket {
              
          private byte[] buffer = new byte[1024];

              
          private DatagramSocket ds = null;

              
          /**
               * 構造函數,創建UDP客戶端
               * 
          @throws Exception
               
          */

              
          public UdpClientSocket() throws Exception {
                  ds 
          = new DatagramSocket();
              }

              
              
          /**
               * 設置超時時間,該方法必須在bind方法之后使用.
               * 
          @param timeout 超時時間
               * 
          @throws Exception
               * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
               * Creation date: 2007-8-16 - 下午10:55:12
               
          */

              
          public final void setSoTimeout(final int timeout) throws Exception {
                  ds.setSoTimeout(timeout);
              }


              
          /**
               * 獲得超時時間.
               * 
          @return 返回超時時間
               * 
          @throws Exception
               * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
               * Creation date: 2007-8-16 - 下午10:55:25
               
          */

              
          public final int getSoTimeout() throws Exception {
                  
          return ds.getSoTimeout();
              }


              
          public final DatagramSocket getSocket() {
                  
          return ds;
              }


              
          /**
               * 向指定的服務端發送數據信息.
               * 
          @param host 服務器主機地址
               * 
          @param port 服務端端口
               * 
          @param bytes 發送的數據信息
               * 
          @return 返回構造后俄數據報
               * 
          @throws IOException
               * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
               * Creation date: 2007-8-16 - 下午11:02:41
               
          */

              
          public final DatagramPacket send(final String host, final int port,
                      
          final byte[] bytes) throws IOException {
                  DatagramPacket dp 
          = new DatagramPacket(bytes, bytes.length, InetAddress
                          .getByName(host), port);
                  ds.send(dp);
                  
          return dp;
              }


              
          /**
               * 接收從指定的服務端發回的數據.
               * 
          @param lhost 服務端主機
               * 
          @param lport 服務端端口
               * 
          @return 返回從指定的服務端發回的數據.
               * 
          @throws Exception
               * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
               * Creation date: 2007-8-16 - 下午10:52:36
               
          */

              
          public final String receive(final String lhost, final int lport)
                      
          throws Exception {
                  DatagramPacket dp 
          = new DatagramPacket(buffer, buffer.length);
                  ds.receive(dp);
                  String info 
          = new String(dp.getData(), 0, dp.getLength());
                  
          return info;
              }


              
          /**
               * 關閉udp連接.
               * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
               * Creation date: 2007-8-16 - 下午10:53:52
               
          */

              
          public final void close() {
                  
          try {
                      ds.close();
                  }
           catch (Exception ex) {
                      ex.printStackTrace();
                  }

              }


              
          /**
               * 測試客戶端發包和接收回應信息的方法.
               * 
          @param args
               * 
          @throws Exception
               * 
          @author <a href="mailto:xiexingxing1121@126.com">AmigoXie</a>
               * Creation date: 2007-8-16 - 下午11:03:54
               
          */

              
          public static void main(String[] args) throws Exception {
                  UdpClientSocket client 
          = new UdpClientSocket();
                  String serverHost 
          = "127.0.0.1";
                  
          int serverPort = 3344;
                  client.send(serverHost, serverPort, (
          "你好,阿蜜果!").getBytes());
                  String info 
          = client.receive(serverHost, serverPort);
                  System.out.println(
          "服務端回應數據:" + info);
              }

          }


             參考文章:http://java.photoshopjiaocheng.com/sun-applet-class/sdk-api-code/virtual-machine-programming-9178.html
                                http://www.eoot.cn/html/pro/java/20070511/25276.html
                                http://topic.csdn.net/t/20060204/19/4539686.html
          posted on 2007-08-16 23:30 阿蜜果 閱讀(15523) 評論(16)  編輯  收藏 所屬分類: 網絡通信相關


          FeedBack:
          # re: Java中的UDP協議編程[未登錄]
          2007-08-16 23:37 | -274°C
          沙發哦。呵呵。
          寫得好。  回復  更多評論
            
          # re: Java中的UDP協議編程
          2007-08-17 01:19 | 楊愛友
          運行過了,以前學過網絡,還比較容易看懂  回復  更多評論
            
          # re: Java中的UDP協議編程
          2007-08-17 10:54 | Scott.Pan
          新文章哦,不錯!
          暫時還沒接觸協議編程,希望有機會向你學習!  回復  更多評論
            
          # re: Java中的UDP協議編程
          2007-08-18 00:00 | 三告習習
          學習,先記下了
          現在都直接用了ice,都還不懂udp...回頭再看看
          :)
            回復  更多評論
            
          # re: Java中的UDP協議編程
          2007-08-20 09:54 | BeanSoft
          保存, 支持. 不理解原理用類庫, 出了問題怎么改? 所以還是要掌握基礎的.  回復  更多評論
            
          # re: Java中的UDP協議編程[未登錄]
          2007-11-15 00:06 | Jack
          非常好,懂了  回復  更多評論
            
          # re: Java中的UDP協議編程
          2007-12-12 14:38 | norvid
          有疑問!
          客戶端中為什么方法
          public final String receive(final String lhost, final int lport) throws Exception;
          的兩個參數lhost, lport在方法體內沒有用到?如果說這兩個參數不起作用,那為什么還要作為參數呢?  回復  更多評論
            
          # re: Java中的UDP協議編程
          2008-01-19 16:28 | Anonymous
          好東西啊~~
          終于找到比較全的UDP編程文章了  回復  更多評論
            
          # re: Java中的UDP協議編程
          2009-05-13 10:08 | 感謝
          不錯的文章  回復  更多評論
            
          # re: Java中的UDP協議編程
          2010-10-06 10:03 | WiHi
          很不錯,很實用,感謝!  回復  更多評論
            
          # re: Java中的UDP協議編程
          2010-12-07 18:45 | 大剛
          好  回復  更多評論
            
          # re: Java中的UDP協議編程
          2011-05-09 23:02 | forth leaf
          要是有個界面就更好了。  回復  更多評論
            
          # re: Java中的UDP協議編程[未登錄]
          2012-06-24 10:45 | wei
          sdfsdf  回復  更多評論
            
          # re: Java中的UDP協議編程[未登錄]
          2012-06-24 10:48 | wei
          想問下大俠java如何接收c++發送過來的結構體。就是接受到結構體后怎么將其還原,具體還原的數據處理能看下嘛?大小端問題我已解決,就是不知道怎么將結構體還原!
          跪求答案,謝謝賜教  回復  更多評論
            
          # re: Java中的UDP協議編程
          2013-10-14 10:58 | danifer
          非常不錯,易懂。  回復  更多評論
            
          # re: Java中的UDP協議編程
          2014-10-27 15:03 | sc
          UDP能正常收發,但是發送DNS報文的時候就不行了,就樓主解救。  回復  更多評論
            
          <2007年8月>
          2930311234
          567891011
          12131415161718
          19202122232425
          2627282930311
          2345678

                生活將我們磨圓,是為了讓我們滾得更遠——“圓”來如此。
                我的作品:
                玩轉Axure RP  (2015年12月出版)
                

                Power Designer系統分析與建模實戰  (2015年7月出版)
                
               Struts2+Hibernate3+Spring2   (2010年5月出版)
               

          留言簿(263)

          隨筆分類

          隨筆檔案

          文章分類

          相冊

          關注blog

          積分與排名

          • 積分 - 2296321
          • 排名 - 3

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 靖州| 儋州市| 松滋市| 呼玛县| 新竹市| 乌兰县| 奉节县| 阿拉善盟| 郎溪县| 阜平县| 北安市| 治县。| 亚东县| 沽源县| 台州市| 维西| 新源县| 乌审旗| 塘沽区| 彭阳县| 郴州市| 宁国市| 康乐县| 桂平市| 嘉荫县| 白玉县| 盘锦市| 巴塘县| 武强县| 凤山县| 宣武区| 山东省| 海口市| 曲水县| 文水县| 临泉县| 东至县| 莆田市| 邳州市| 郴州市| 南康市|