《Java程式設計藝術》章節選登。作者:高永強 清華大學出版社 (即将出版)
資料報表Datagram,或稱數報式資料傳輸技術,利用UDP通訊協定(User Datagram Protocol),進行使用者-伺服器間的資料傳遞,但Java虛拟機将UDP 底層通訊細節隐藏,程式設計人員不必顧及其通訊協定和過程,隻需利用java.net包中提供的API類DatagramSocket和DatagramPacket進行程式設計,調用适當的方法,實作使用者-伺服器程式設計。其中DatagrameScoket用來建立端口間的通訊,而DatagramPacket用來擷取通過網絡位址和端口以郵包方式(Packet)發送來的資訊。表23.4列出了java.net包中DataramSocket和DataramPacket的常用構造器以及方法。
表23.4 DatagramSocket和DatagramPacket類的常用構造器以及方法
構造器/方法
解 釋
DatagramSocket(int port,InetAdrress address)
按指定端口和網際網路位址建立對象。
close()
關閉插座連接配接。
connect(InetAddress address, int port)
按指定網際網路位址和端口連接配接。
disconnect()
斷開目前的連接配接。
InetAddress getInetAddress()
傳回目前數報插座的網際網路位址。
InetAddress getLocalAddress()
傳回目前數報插座的本機位址
int getPort()
傳回目前數報插座的連接配接端口。
int getLocalPort()
傳回目前數報插座的本機連接配接端口。
receive(DatagramPacket packet)
接收目前數報插座的郵件。
send(DatagramPacket packet)
發送目前數報插座的郵件。
DatagramPacket(byte[] buf, int length)
按指定緩沖數組合長度建立擷取郵包的對象。
InetAddress getAddress()
傳回目前進行郵包傳送的網際網路位址。
Byte[] getData()
傳回目前發送或接收資料緩沖數組。
int getLength()
傳回目前發送或接收資料的長度。
傳回目前發送或接收資料的端口。
注意 DatagramSocket和DatagramPacket抛出檢查性異常,程式中必須提供處理這些異常的代碼。具體執行個體見下面的讨論。
下面的例子利用DatagramSocket和DatagramPacket,模拟使用者-伺服器通訊,将使用者 的英文輸入,通過郵包發送到伺服器端程式,轉換為大寫字母,并将結果傳回到使用者屏 幕。其功能類似于在Socket和ServerSocket讨論過的程式,但增加了統計并傳回郵包長度的操作。圖23.7顯示了這個例子的一個典型運作結果。圖上方為伺服器端程式運作後的截圖。(注:截圖未能顯示。請參考原書)
圖23.7 利用Datagram的典型運作結果
如下是利用Datagram編寫的伺服器端程式的代碼:
//這個程式存在本書配套資源目錄Ch23名為DatagramServerTest.java
import java.io.*;
import java.net.*;
public class DatagramServerTest {
public static void main(String[] args) {
System.out.println(\"Welcome! The server is running....\");
String line = \"Datagram packet from server: I love Java programming.\\n\";
String promptString = line.toUpperCase() + \"Enter quit to STOP\";
try {
DatagramSocket socket = new DatagramSocket(1688);
//建立指定端口的Datagram
DatagramPacket receivePacket; //聲明接收郵包
byte[] buf = new byte[256]; //緩沖器
receivePacket = new DatagramPacket(buf, buf.length);
//建立接收郵包
socket.receive(receivePacket); //接收郵包
buf = promptString.getBytes(); //内容至緩沖
InetAddress address = receivePacket.getAddress();
//得到接收位址
int port = receivePacket.getPort();//得到接收端口
sending(socket, buf, buf.length, address, port);
//調用發送郵包方法
while (true) {
buf = new byte[256]; //清除緩沖
receivePacket = new DatagramPacket(buf, buf.length);
//建立新郵包
socket.receive(receivePacket); //接收
String receive = new String(receivePacket.getData()); //得到郵包内容
buf = receive.toUpperCase().getBytes();
//内容轉成大寫并送往緩沖
sending(socket, buf, buf.length, address, port);//發送
buf = new byte[256]; //清除緩沖
String wordCount = \"(Converting from server and packet length: \" + receive.trim().length() + \")\";
receivePacket = new DatagramPacket(buf, buf.length); //建立新郵包
buf = wordCount.getBytes(); //發件内容送往緩沖
sending(socket, buf, buf.length, address, port);
//調用發送方法
}
}
catch (IOException e) {
e.printStackTrace();
}
//發送郵件方法
public static void sending(DatagramSocket socket, byte[] buf, int length, InetAddress address, int port) {
DatagramPacket sendPacket = new DatagramPacket(buf, length, address, port);
try {
socket.send(sendPacket); //發送
}catch (IOException e) {
e.printStackTrace();
}
}
}
代碼中首先接收使用者端發送過來的一個空郵包,并利用這個郵包發送慰問和提示資訊到使用者。在循環中,接收使用者發來的郵包内容,并将其轉換成大寫字母、統計字元串即郵包長度,調用自定義靜态方法sending()将結果郵包發還給發來的使用者。代碼中在重新利用緩沖器發送新内容時,利用重新定義緩沖器來清除其原有内容。(待續
本文轉自高永強51CTO部落格,原文連結: http://blog.51cto.com/yqgao/157391,如需轉載請自行聯系原作者