所謂的UDP( User Datagram Protocol )協議指的是用戶數據報,在網絡中它與TCP協議一樣用於處理數據包。在OSI模型中,在第四層——傳輸層,處於IP協議的上一層。
UDP是一種無連接的協議,每個數據報都是一個獨立的信息,包括完整的源或目的地址,它在網絡上以任何可能的路徑傳往目的地,因此能否到達目的地,到達目的地的時間以及內容的正確性都是不能被保證的。
既然如此,那麼我們為什麼還要使用UDP協議進行編程呢?
那是因為,在網絡質量令人不十分滿意的環境下,UDP協議數據包丟失會比較嚴重。但是由於UDP的特性:它不屬於連接型協議,因而具有資源消耗小,處理速度快的優點,所以通常音頻、視頻和普通數據在傳送時使用UDP較多,因為它們即使偶爾丟失一兩個數據包,也不會對接收結果產生太大影響。比如聊天用的ICQ和OICQ
在Java中操縱UDP
使用位於JDK中Java.net包下的DatagramSocket和DatagramPacket類,就可以非常方便地控制用戶數據報文了。
其中,DatagramSocket類:創建接收和發送UDP的Socket實例
值得注意的是,在創建DatagramSocket類實例時,如果端口已經被使用,會產生一個SocketException的異常拋出,並導致程序非法終止,這個異常應該注意捕獲。
還有一些重要的實現方法,如:
receive(DatagramPacket d):接收數據報文到d中。receive方法產生一個“阻塞”。
send(DatagramPacketd):發送報文d到目的地。
setSoTimeout(inttimeout):設置超時時間,單位為毫秒。
close():關閉DatagramSocket。在應用程序退出的時候,通常會主動釋放資源,關閉
Socket,但是由於異常地退出可能造成資源無法回收。所以,應該在程序完成時,主動使用此方法關閉Socket,或在捕獲到異常拋出後關閉Socket。
注意:“阻塞”是一個專業名詞,它會產生一個內部循環,使程序暫停在這個地方,直到一個條件觸發。
實現UDP編程會使用到的另一個十分重要的類,DatagramPacket類。
DatagramPacket:用於處理報文,將byte數組、目標地址、目標端口等數據包裝成報文或者將報文拆卸成byte數組。
DatagramPacket(byte[] buf, int length, InetAddress addr, int port):從buf數組中,取出length長的數據創建數據包對象,目標是addr地址,port端口。
DatagramPacket(byte[] buf, int offset, int length, InetAddressaddress, int port):從buf數組中,取出offset開始的、length長的數據創建數據包對象,目標是addr地址,port端口。
DatagramPacket(byte[] buf, int offset, int length):將數據包中從offset開始、length長的數據裝進buf數組。
DatagramPacket(byte[] buf, int length):將數據包中length長的數據裝進buf數組。
getData():它從實例中取得報文的byte數組編碼。
使用UDP協議編程,最主要的是編寫發送端和接收端的程序。對於這兩部分代碼的編寫,也是非常容易的,因為,它們都有一定的編寫步驟和規范。
如對於發送端的編寫:
發送端
建立udpsocket服務端點。該端點建立,系統會隨機分配一個端口。如果不想隨機配置,可以手動指定。
DatagramSocket ds = new DatagramSocket(9002);
將數據進行packet包的封裝,必須要指定目的地地址和端口。
byte[] buf = "wo shi shu ju".getBytes();
DatagramPacket dp=newDatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.254"),9001);
通過socket服務的send方法將該包發出。
ds.send(dp);
將socket服務關閉。主要是關閉資源。
ds.close();
這樣,就完成了對於發送端的編寫工作了。另外,
接收端
建立udpsocket服務端點。該端點建立,系統會隨機分配一個端口。如果不想隨機配置,可以手動指定。
DatagramSocket ds = new DatagramSocket(9002);
將數據進行packet包的封裝,必須要指定目的地地址和端口。
byte[] buf = "wo shi shu ju".getBytes();
DatagramPacket dp=newDatagramPacket(buf,buf.length,InetAddress.getByName("192.168.1.254"),9001);
通過socket服務的send方法將該包發出。
ds.send(dp);
將socket服務關閉。主要是關閉資源。
ds.close();
關於發送端和接收端應用的兩個程序:
發送端:
package net.csdn.udt;
import java.net.DatagramPacket;
import java.net.DatagramSocket;
import java.net.InetAddress;
import java.net.InetSocketAddress;
public class Send {
/**
* @param args
*/
public static voidmain(String[] args)throws Exception {
//建立udpsocket服務端點。該端點建立,系統會隨機分配一個端口。
DatagramSocket ds = new DatagramSocket();
//將數據進行packet包的封裝,必須要指定目的地地址和端口。
byte [] buf ="wo shi shu ju".getBytes();
//創建數據報對象
String host = "192.168.49.110";
InetAddress ia = InetAddress.getByName(host);
DatagramPacket dp = new DatagramPacket(buf,buf.length, ia,3366);
//通過socket服務的send方法將該包發出。
ds.send(dp);
//將socket服務關閉。主要是關閉資源。
ds.close();
}
}
接收端:
packagenet.csdn.udt;
importjava.net.DatagramPacket;
importjava.net.DatagramSocket;
importjava.net.InetAddress;
public classReceive {
/**
*@param args
*/
public static void main(String[] args)throws Exception{
//創建一個udt的接收對象
DatagramSocket ds =newDatagramSocket(9009);
//將接收的數據封裝成數據包中
byte[] buf = new byte [1024];
//創建數據報對象
DatagramPacket dp = newDatagramPacket(buf,buf.length);
//接收數據報
ds.receive(dp);
//輸出
//InetAddress host = dp.getAddress();
String data =new String(dp.getData());
String host =dp.getAddress().getHostAddress();
int port =dp.getPort();
System.out.println("data:\t"+data+"host:\t"+host+"port:\t"+port);
ds.close();
}
}
對於Socket編程的一些方法步驟,我們一定要熟記並且要經常練習、運用以免忘記,因為,它還是挺重要的。