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

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

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

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

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

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

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

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

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

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

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

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

          四. 實例解析
              下面讓我們來看一個UDP的服務端和客戶端交互通信的例子,在本例中,服務端循環(huán)等待客戶端發(fā)送的信息,并對其進行回應,客戶端向服務端發(fā)送信息,并接收服務端的回應信息。代碼如下:
              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;

              
          /**
               * 構造函數(shù),綁定主機和端口.
               * 
          @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();
              }


              
          /**
               * 綁定監(jiān)聽地址和端口.
               * 
          @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);
              }



              
          /**
               * 接收數(shù)據(jù)包,該方法會造成線程阻塞.
               * 
          @return 返回接收的數(shù)據(jù)串信息
               * 
          @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;
              }


              
          /**
               * 將響應包發(fā)送給請求端.
               * 
          @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);
              }


              
          /**
               * 獲得發(fā)送回應的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監(jiān)聽口.
               * 
          @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客戶端程序,用于對服務端發(fā)送數(shù)據(jù),并接收服務端的回應信息.
           * 
          @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;

              
          /**
               * 構造函數(shù),創(chuàng)建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;
              }


              
          /**
               * 向指定的服務端發(fā)送數(shù)據(jù)信息.
               * 
          @param host 服務器主機地址
               * 
          @param port 服務端端口
               * 
          @param bytes 發(fā)送的數(shù)據(jù)信息
               * 
          @return 返回構造后俄數(shù)據(jù)報
               * 
          @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;
              }


              
          /**
               * 接收從指定的服務端發(fā)回的數(shù)據(jù).
               * 
          @param lhost 服務端主機
               * 
          @param lport 服務端端口
               * 
          @return 返回從指定的服務端發(fā)回的數(shù)據(jù).
               * 
          @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();
                  }

              }


              
          /**
               * 測試客戶端發(fā)包和接收回應信息的方法.
               * 
          @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(
          "服務端回應數(shù)據(jù):" + 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 阿蜜果 閱讀(15530) 評論(16)  編輯  收藏 所屬分類: 網(wǎng)絡通信相關


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

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

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

          留言簿(263)

          隨筆分類

          隨筆檔案

          文章分類

          相冊

          關注blog

          積分與排名

          • 積分 - 2299173
          • 排名 - 3

          最新評論

          閱讀排行榜

          評論排行榜

          主站蜘蛛池模板: 双辽市| 旅游| 甘洛县| 忻城县| 越西县| 德清县| 中西区| 云安县| 四子王旗| 图们市| 南投县| 井陉县| 湘潭县| 余庆县| 扎囊县| 榆社县| 临海市| 承德县| 黔东| 手机| 佛坪县| 保山市| 贺州市| 泗洪县| 克什克腾旗| 芜湖市| 绥芬河市| 喀什市| 小金县| 武胜县| 沭阳县| 大厂| 鄂州市| 舟曲县| 会昌县| 株洲市| 酒泉市| 新绛县| 深泽县| 营口市| 阳信县|