1. 程式人生 > >Java網路程式設計:UDP DatagramSocket

Java網路程式設計:UDP DatagramSocket

原文地址

DatagramSocket類是java通過UDP通訊的途徑。UDP仍位於IP層的上面。 你可以用DatagramSocket類傳送和接收UDP資料包。

UDP 和TCP

UDP工作方式和TCP有點不同。當你通過TCP傳送資料時,你先要建立連線。一旦TCP連線建立了,TCP會保證你的資料傳遞到對端,否則它將告訴你已發生的錯誤。

僅僅用UDP來發送資料包(datagrams)到網路間的某個IP地址。你不能保證資料會不會到達。你也不能保證UDP資料包到達接收方的指令。這意味著UDP比TCP有更少的協議開銷(無完整檢查流)。

當資料傳輸過程中不在乎資料包是否丟失時,UDP就比較適合這樣的資料傳輸。比如,網上的電視訊號的傳輸。你希望訊號到達客戶端時儘可能地接近直播。因此,如果丟失一兩個畫面,你一點都不在乎。你不希望直播延遲,值想確保所有的畫面顯示在客戶端。你寧可跳過丟失的畫面,希望一直看到最新的畫面。

這種情況也會發生在網上攝像機直播節目中。誰會關心過去發生的什麼,你只想顯示當前的畫面。你不希望比實際情況慢30s結束,只因為你想看到攝像機顯示給觀眾的所有畫面。這跟攝像機錄影有點不同。從攝像機錄製畫面到磁碟,你不希望丟失一個畫面。你可能還希望有點延遲,如果有重大的情況發生,就不需要倒回去檢查畫面。

通過DatagramSocket傳送資料

通過Java的DatagramSocket類傳送資料,首先需要建立DatagramPacket。如下:

buffer = new byte[65508]; 

InetAddress address = new DatagramPacket(buffer, buffer.length, address,9000);

位元組緩衝塊(位元組陣列)就是UDP資料包中用來發送的資料。緩衝塊上限長度為65508位元組,是單一UDP資料包傳送的最大的資料量。

資料包建構函式的長度就是快取塊中用於傳送的資料的長度。所有多於最大容量的資料都會被忽略。

包含節點(例如伺服器)地址的InetAddress例項攜帶節點(如伺服器)的地址傳送的UDP資料包。InetAddress類表示一個ip地址(網路地址)。getByName()方法返回帶有一個InetAddress例項,該例項帶有匹配主機名的ip地址。

埠引數是UDP埠伺服器用來接收正在監聽的資料。UDP埠和TCP埠是不一樣的。一臺電腦同時有不同的程序監聽UDP和TCP 80埠。

為了傳送資料包,你需要建立DatagramSocket來發送資料。如下:

DatagramSocketdatagramSocket = new DatagramSocket();

呼叫send()方法傳送資料,像這樣:

datagramSocket.send(packet);

完整示例:

DatagramSocketdatagramSocket = new DatagramSocket();

byte[] buffer = "0123456789".getBytes();

InetAddressreceiverAddress = InetAddress.getLocalHost();

DataframPacket packet = new DatagramPacket( buffer, buffer.length, receiverAddress,80);
datagramSocket.send(packet);

從DatagramSocket獲取資料

從DataframSocket獲取資料時,首先建立DataframPacket ,然後通過DatagramSocket類的receive()方法接收資料。例如:

DatagramSocketdatagramSocket = new DatagramSocket(80);

byte[] buffer = new byte[10];

DatagramPacket packet = new DatagramPacket(buffer, buffer.length);

datagramSocket.receive(packet);

注意DatagramSocket是如何通過傳遞引數80到它的構造器初始化的。這個引數是UDP埠的DatagramSocket用來接收UDP資料包的。像之前提到的,TCP和UDP埠是不一樣的,也不重疊。你可以有倆個不同的程序同時在埠80監聽TCP和UDP,沒有任何衝突。

第二,位元組快取塊和DatagramPacket建立了。注意DatagramPacket是沒有關於節點如何傳送資料的資訊的,當建立一個方資料的DatagramPacket時,它會直到這個資訊。這就是為什麼我們會用DatagramPacket接收資料而不是傳送資料。因此沒有目標地址是必須的。

最後,呼叫DatagramSocket的receive()方法。直到資料包接收到為止,這個方法都是阻塞的。

接收的資料位於DatagramPacket的位元組緩衝塊。緩衝塊可以通過呼叫getData()獲得:

byte[] buffer = packet.getData();

緩衝塊接收了多少的資料需要你去找出來。你用的協議應該定義每個UDP包發多少資料,活著定義一個你能找到的資料結束標記。
一個真正的服務端程式可能會在一個loop中呼叫receive()方法,傳送所有接收到的DatagramPacket到工作的執行緒池中,就像TCP伺服器處理請求連線一樣(檢視Java Multithreaded Servers獲取更多詳情)