2.3 UDP通訊端
UDP協議提供了一種不同於TCP協議的端對端服務,實際上UDP只實現了兩個功能:1)、
在IP協議的基礎上添加了另一層地址(連接埠)2)、對資料轉送過程中可能產生的錯誤進行了檢測,並拋棄了已損壞的資料。
UDP通訊端與TCP通訊端的不同點:
1. UDP協議在使用前不需要進行串連。
2. UDP協議儲存邊界資訊。
2.3.1 UDP用戶端
UDP用戶端首先向被動等待聯絡的伺服器發送一個資料報文。一個UDP報文要執行以下三步。
1. 建立一個DatagramSocket執行個體,可以選擇對本地地址和連接埠號碼進行設定。 2. 使用DatagramSocket類的send() 和 receive()方法來發送和接收DatagramPacket執行個體,進行通訊。 3. 通訊完成後,使用DatagramSocket類的close()方法來銷毀該通訊端。 |
DatagramSocket建立的時候不需要指定目的地址。因為UDP通訊前不需要進行串連。每個資料報可以發送到或者接收於不同的目的地址。
UDP協議的一個後果是會出現資料報文丟失。為了避免這個問題,可以設定最大阻塞時間。
下面一個UDP用戶端的例子
package com.suifeng.tcpip.chapter2;import java.io.IOException;import java.io.InterruptedIOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;import java.net.SocketException;import java.net.UnknownHostException;/** * UDP 用戶端 * * @author Suifeng * */public class UDPEchoClientTimeout{// 逾時時間private static final int TIMEOUT = 3000;// 最大串連次數private static final int MAXTRIES = 5;public static void main(String[] args) throws IOException{if (args.length < 2 || args.length > 3){throw new IllegalArgumentException("Paramters:<Server> <Word> [<Port>]");}// 伺服器位址InetAddress serverAddress = InetAddress.getByName(args[0]);// 要發送的資料byte[] byteToSend = args[1].getBytes();// 伺服器連接埠int serverPort = (args.length == 3) ? Integer.parseInt(args[2]) : 7;// UDP用戶端DatagramSocket socket = new DatagramSocket();// 接收資料阻塞時間socket.setSoTimeout(TIMEOUT);System.out.println("UDP 用戶端已建立....");// 發送資料報包DatagramPacket sendPacket = new DatagramPacket(byteToSend,byteToSend.length, serverAddress, serverPort);// 接收的資料報包DatagramPacket receiverPacket = new DatagramPacket(new byte[byteToSend.length], byteToSend.length);// 嘗試接收次數int tries = 0;boolean receivedResponse = false;do{System.out.println("向服務區端發送資料....");// 向伺服器端發送資料socket.send(sendPacket);try{System.out.println("接收從伺服器端返回的資料...");// 從伺服器端接收資料socket.receive(receiverPacket);if (!receiverPacket.getAddress().equals(serverAddress)){throw new IOException("Received packet from an unknown source");}receivedResponse = true;}catch (InterruptedIOException e){tries++;System.out.println("Timed out," + (MAXTRIES - tries)+ " more ties");}} while ((!receivedResponse) && (tries < MAXTRIES));if(receivedResponse){System.out.println("Received:"+new String(receiverPacket.getData()));}else{System.out.println("No response--giving up!");}}}
2.3.2 UDP伺服器端
與TCP伺服器一樣,UDP伺服器是建一個幾個通訊終端,並被動等待用戶端發起串連。
典型的UDP伺服器執行需要以下三步。
1. 建立一個DatagramSocket執行個體,指定本地連接埠號碼,並可以選擇指定本地地址。此時,伺服器已經準備好從任何用戶端接收資料報文。 2. 使用DatagramSocket類的receive()方法來接收一個DatagramPacket執行個體。當receive()方法返回時,資料報文就包含了用戶端的地址,這樣我們就知道了回複資訊應該發送到什麼地方。 3. 使用DatagramSocket類的send() 和receive()方法來發送和接收DatagramPackets執行個體,進行通訊。 |
下面的例子是使用UDP將用戶端發送過來的訊息會發給用戶端的。
package com.suifeng.tcpip.chapter2;import java.io.IOException;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.SocketException;/** * UDP伺服器端 * * @author Suifeng * */public class UDPEchoServer{// 最大顯示數組位元組數private static final int ECHO_MAX = 255;public static void main(String[] args) throws IOException{if (args.length != 1){throw new IllegalArgumentException("Parameter:<Port>");}// 伺服器連接埠int serverPort = Integer.parseInt(args[0]);// 伺服器端DatagramSocket socket = new DatagramSocket(serverPort);// 資料報DatagramPacket packet = new DatagramPacket(new byte[ECHO_MAX], ECHO_MAX);System.out.println("UDP伺服器已啟動....");while (true){System.out.println("正在等待用戶端發送資料....");// 接收用戶端發送的資料(阻塞)socket.receive(packet);System.out.println("Handing client at "+ packet.getAddress().getHostAddress() + " on port "+ packet.getPort());System.out.println("Received Data:"+new String(packet.getData()));// 向用戶端發送資料(這裡只是將資料包進行轉寄--透傳,沒有進行任何處理)socket.send(packet);// 重設緩衝區大小packet.setLength(ECHO_MAX);}}}
先啟用伺服器端,監聽39393連接埠
在啟用用戶端發送資料
再查看伺服器端