注意:IP地址224.0.0.1 到 239.255.255.255(包括)均為保留的多點(diǎn)傳送組地址。
網(wǎng)絡(luò )API通過(guò)MulticastSocket類(lèi)和MulticastSocket,以及一些輔助類(lèi)(比如NetworkInterface) 支持多點(diǎn)傳送,當一個(gè)客戶(hù)程序要加入多點(diǎn)傳送組時(shí),就創(chuàng )建一個(gè)MulticastSocket對象。MulticastSocket(int port) 構造函數允許應用程序指定端口(通過(guò)port參數)接收自尋址包,端口必須與服務(wù)程序的端口號相匹配,要加入多點(diǎn)傳送組,客戶(hù)程序調用兩個(gè) joinGroup()方法中的一個(gè),同樣要離開(kāi)傳送組,也要調用兩個(gè)leaveGroup()方法中的一個(gè)。
由于MulticastSocket擴展了DatagramSocket類(lèi),一個(gè)MulticastSocket對象就有權訪(fǎng)問(wèn)DatagramSocket方法。
List6是MCClient的源代碼,這段代碼示范了一個(gè)客戶(hù)端加入多點(diǎn)傳送組的例子。
Listing 6: MCClient.java
// MCClient.java
import java.io.*;
import java.net.*;
class MCClient
{
public static void main (String [] args) throws IOException
{
// Create a MulticastSocket bound to local port 10000. All
// multicast packets from the server program are received
// on that port.
MulticastSocket s = new MulticastSocket (10000);
// Obtain an InetAddress object that contains the multicast
// group address 231.0.0.1. The InetAddress object is used by
// DatagramPacket.
InetAddress group = InetAddress.getByName ("231.0.0.1");
// Join the multicast group so that datagram packets can be
// received.
s.joinGroup (group);
// Read several datagram packets from the server program.
for (int i = 0; i < 10; i++)
{
// No line will exceed 256 bytes.
byte [] buffer = new byte [256];
// The DatagramPacket object needs no addressing
// information because the socket contains the address.
DatagramPacket dgp = new DatagramPacket (buffer,
buffer.length);
// Receive a datagram packet.
s.receive (dgp);
// Create a second byte array with a length that matches
// the length of the sent data.
byte [] buffer2 = new byte [dgp.getLength ()];
// Copy the sent data to the second byte array.
System.arraycopy (dgp.getData (),
0,
buffer2,
0,
dgp.getLength ());
// Print the contents of the second byte array. (Try
// printing the contents of buffer. You will soon see why
// buffer2 is used.)
System.out.println (new String (buffer2));
}
// Leave the multicast group.
s.leaveGroup (group);
// Close the socket.
s.close ();
}
}
MCClient創(chuàng )建了一個(gè)綁定端口號10000的MulticastSocket對象,接下來(lái)他獲得了一個(gè)InetAddress子類(lèi)對象,該子類(lèi) 對象包含多點(diǎn)傳送組的IP地址231.0.0.0,然后通過(guò)joinGroup(InetAddress addr)方法加入多點(diǎn)傳送組中,接下來(lái) MCClient接收10個(gè)自尋址包,同時(shí)輸出他們的內容,然后使用leaveGroup(InetAddress addr)方法離開(kāi)傳送組,最后關(guān)閉 套接字。
也許你對使用兩個(gè)字節數組buffer 和 buffer2感到奇怪,當接收到一個(gè)自尋址包后,getData()方法返回一個(gè)引用,自尋址包 的長(cháng)度是256個(gè)字節,如果要輸出所有數據,在輸出完實(shí)際數據后會(huì )有很多空格,這顯然是不合理的,所以我們必須去掉這些空格,因此我們創(chuàng )建一個(gè)小的字節數 組buffer2,buffer2的實(shí)際長(cháng)度就是數據的實(shí)際長(cháng)度,通過(guò)調用DatagramPacket's getLength()方法來(lái)得到這個(gè)長(cháng) 度。從buffer 到 buffer2快速復制getLength()的長(cháng)度的方法是調用System.arraycopy()方法。
List7 MCServer的源代碼顯示了服務(wù)程序是怎樣工作的。
Listing 7: MCServer.java
// MCServer.java
import java.io.*;
import java.net.*;
class MCServer
{
public static void main (String[] args) throws IOException
{
System.out.println ("Server starting...\n");
// Create a MulticastSocket not bound to any port.
MulticastSocket s = new MulticastSocket ();
// Because MulticastSocket subclasses DatagramSocket, it is
// legal to replace MulticastSocket s = new MulticastSocket ();
// with the following line.
// DatagramSocket s = new DatagramSocket ();
// Obtain an InetAddress object that contains the multicast
// group address 231.0.0.1. The InetAddress object is used by
// DatagramPacket.
InetAddress group = InetAddress.getByName ("231.0.0.1");
// Create a DatagramPacket object that encapsulates a reference
// to a byte array (later) and destination address
// information. The destination address consists of the
// multicast group address (as stored in the InetAddress object)
// and port number 10000 -- the port to which multicast datagram
// packets are sent. (Note: The dummy array is used to prevent a
// NullPointerException object being thrown from the
// DatagramPacket constructor.)
byte [] dummy = new byte [0];
DatagramPacket dgp = new DatagramPacket (dummy,
0,
group,
10000);
// Send 30000 Strings to the port.
for (int i = 0; i < 30000; i++)
{
// Create an array of bytes from a String. The platform's
// default character set is used to convert from Unicode
// characters to bytes.
byte [] buffer = ("Video line " + i).getBytes ();
// Establish the byte array as the datagram packet's
// buffer.
dgp.setData (buffer);
// Establish the byte array's length as the length of the
// datagram packet's buffer.
dgp.setLength (buffer.length);
// Send the datagram to all members of the multicast group
// that listen on port 10000.
s.send (dgp);
}
// Close the socket.
s.close ();
}
}
MCServer創(chuàng )建了一個(gè)MulticastSocket對象,由于他是DatagramPacket對象的一部分,所以他沒(méi)有綁定端口 號,DatagramPacket有多點(diǎn)傳送組的IP地址(231.0.0.0),一旦創(chuàng )建DatagramPacket對象,MCServer就進(jìn)入一 個(gè)發(fā)送30000條的文本的循環(huán)中,對文本的每一行均要創(chuàng )建一個(gè)字節數組,他們的引用均存儲在前面創(chuàng )建的DatagramPacket對象中,通過(guò) send()方法,自尋址包發(fā)送給所有的組成員。
在編譯了MCServer 和 MCClient后,通過(guò)輸入java MCServer開(kāi)始運行MCServer,最后再運行一個(gè)或多個(gè)MCClient。
結論
本文通過(guò)研究套接字揭示了Java的網(wǎng)絡(luò )API的應用方法,我們介紹了套接自的慨念和套接字的組成,以及流套接字和自尋址套接字,以及如何使用 InetAddress, Socket, ServerSocket, DatagramPacket, DatagramSocket和 MulticastSocket類(lèi)。在完成本文后就可以編寫(xiě)基本的底層通訊程序。
文章來(lái)源于領(lǐng)測軟件測試網(wǎng) http://kjueaiud.com/