Datagram socketDatagram socket使用UDP來實現資料通訊,因此它不能保證資料能夠到達目的地,但是由於它不需要專用的網路連結,所以它所需的資源相對少的多。 Datagram以包的方式發送資料,但它不能保證這些資料包以特定的順序到達目的,因此包中往往需要包含序號的資訊,接收方可以根據序號的資訊決定是否所有的包都已收到,並按正常順序重組這些包。 Java通過兩個類DatagramSocket和DatagramPacket來支援Datagram socket。DatagramSocket實現了Datagram socket的準系統,而DatagramPacket則提供了對包的一些支援。 DatagramSocket的幾個重要方法: (1) DatagramSocket():隨機綁定一個有效連接埠; (2) DatagramSocket(int port):綁定指定的連接埠; (3) Void send(DatagramPacket p):發送資料報,由於目的地的地址資訊已包含在資料報中,所以不需要在本函數中提供地址資訊; (4) synchronized void receive(DatagramPacket p):接收資料包,安全執行緒; (5) synchronized void close():關閉socket; 在DatagramSocket中並不區分ServerSocket和ClientSocket,如果一定要區分,那麼發送的是client,而接收的是server。 DatagramPacket有以幾個重要的方法: (1) DatagramPacket(byte ibuf[], int ilength):用於接收資料報; (2) DatagramPacket(byte ibuf[], int ilength, InetAddress iaddr, int iport):用於發送的資料報; (3) byte[] getData(); (4) int getLength() 以下是完整的Datagram Socket的例子:
接收端,Server端代碼: import java.io.*;
import java.net.*;
class FortuneServer1 extends Thread
{
DatagramSocket ServerSocket;
public FortuneServer1()
{
super("FortuneServer1");
try
{
ServerSocket = new DatagramSocket(1114);
System.out.println("FortuneServer up and running...");
}
catch (SocketException e)
{
System.err.println("Exception: couldn't create datagram socket");
System.exit(1);
}
} public static void main(String[] args)
{
FortuneServer1 server = new FortuneServer1();
server.start();
} public void run()
{
if (ServerSocket == null)
return;
while (true)
{
try
{
InetAddress address;
int port;
DatagramPacket packet;
byte[] data = new byte[128];
packet = new DatagramPacket(data, data.length);
ServerSocket.receive(packet);
//如果1114連接埠沒有請求到資料,就一直停留在這裡等待資料接收
//如果接收到資料,則將資料包放在packet對象中,並在下面對其解析
address = packet.getAddress();
port = packet.getPort();
FileWriter fw = new FileWriter("Fortunes.txt");//建立新檔案
PrintWriter out = new PrintWriter(fw);
for(int i=0;i<data.length;i++){
out.print(data[i]+" ");
}
out.close();
System.out.println("Data has been writen to destination!");
//再次建立資料包,發送到接收的資料的連接埠
packet = new DatagramPacket(data, data.length, address, port);
ServerSocket.send(packet);
System.out.println("Respond has been made!");
}
catch (Exception e)
{
System.err.println("Exception: " + e);
e.printStackTrace();
}
}
}
}
說明:(1) 這個例子中接收端的socket使用了多線程;(2) 在建構函式中建立了DatagramSocket,並且使用了1114這個連接埠;(3) 本例子的關鍵函數是run,它使用了死迴圈,在迴圈中使用了receive這方法來臨聽1114連接埠,如果1114連接埠沒有請求資料到來,那麼這個程式就一直停留在receive這個位置,不再往下執行; (4) 當1114端有資料時,receive方法將接收到的DatagramPacket資料包放在packet這個對象中,然後解析其中的資料,擷取發送方的地址資訊;(5) 然後再建立DatagramPacket包,並填充資料,發送到原接收端。
以下是發送端的代碼:import java.net.*; class FortuneClient
{
public static void main(String args[])
{
FortuneClient client = new FortuneClient();
System.out.println(client.getMessage());
} public String getMessage()
{
String fortune;
try {
DatagramSocket socket;
DatagramPacket packet;
byte[] data = new byte[128];
for(int i=0;i<data.length;i++){
Integer integer=new Integer(i);
data[i]=integer.byteValue();
}
socket = new DatagramSocket();
//packet = new DatagramPacket(data, data.length,InetAddress.getByName("127.0.0.1"), 1114);
packet = new DatagramPacket(data, data.length,InetAddress.getLocalHost(), 1114);
socket.send(packet);
packet = new DatagramPacket(data, data.length);
socket.receive(packet);
fortune = new String(packet.getData());
socket.close();
}
catch (UnknownHostException e) {
System.err.println("Exception: host could not be found");
return null;
}
catch (Exception e) {
System.err.println("Exception: " + e);
e.printStackTrace();
return null;
}
return fortune;
}
}
用戶端的代碼與伺服器端的代碼基本相同,只是沒有了迴圈,並且處理步驟與伺服器端的基本相反。這也說明了Datagram Socket不真正區分Server和Client。