程序師世界是廣大編程愛好者互助、分享、學習的平台,程序師世界有你更精彩!
首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫知識
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
 程式師世界 >> 編程語言 >> JAVA編程 >> 關於JAVA >> Java套接字編程(下)(3)

Java套接字編程(下)(3)

編輯:關於JAVA

多點傳送和MulticastSocket類

  前面的例子顯示了服務器程序線程發送單一的消息(通過流套接字或自尋址套接字)給唯一的客戶端程序,這種行為被稱為單點傳送(unicasting),多數情況都不適合於單點傳送,比如,搖滾歌手舉辦一場音樂會將通過互聯網進行播放,畫面和聲音的質量依賴於傳輸速度,服務器程序要傳送大約10億字節的數據給客戶端程序,使用單點傳送,那麼每個客戶程序都要要復制一份數據,如果,互聯網上有10000個客戶端要收看這個音樂會,那麼服務器程序通過Internet要傳送10000G的數據,這必然導致網絡阻塞,降低網絡的傳輸速度。

  如果服務器程序要將同一信息發送給多個客戶端,那麼服務器程序和客戶程序可以利用多點傳送(multicasting)方式進行通信。多點傳送就是服務程序對專用的多點傳送組的IP地址和端口發送一系列自尋址數據包,通過加入操作IP地址被多點傳送Socket注冊,通過這個點客戶程序可以接收發送給組的自尋址包(同樣客戶程序也可以給這個組發送自尋址包),一旦客戶程序讀完所有要讀的自尋址數據包,那麼可以通過離開組操作離開多點傳送組。

  注意:IP地址224.0.0.1 到 239.255.255.255(包括)均為保留的多點傳送組地址。

  網絡API通過MulticastSocket類和MulticastSocket,以及一些輔助類(比如NetworkInterface)支持多點傳送,當一個客戶程序要加入多點傳送組時,就創建一個MulticastSocket對象。MulticastSocket(int port)構造函數允許應用程序指定端口(通過port參數)接收自尋址包,端口必須與服務程序的端口號相匹配,要加入多點傳送組,客戶程序調用兩個joinGroup()方法中的一個,同樣要離開傳送組,也要調用兩個leaveGroup()方法中的一個。

  由於MulticastSocket擴展了DatagramSocket類,一個MulticastSocket對象就有權訪問DatagramSocket方法。

  List6是MCClIEnt的源代碼,這段代碼示范了一個客戶端加入多點傳送組的例子。

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創建了一個綁定端口號10000的MulticastSocket對象,接下來他獲得了一個InetAddress子類對象,該子類對象包含多點傳送組的IP地址231.0.0.0,然後通過joinGroup(InetAddress addr)方法加入多點傳送組中,接下來MCClIEnt接收10個自尋址包,同時輸出他們的內容,然後使用leaveGroup(InetAddress addr)方法離開傳送組,最後關閉套接字。

  也許你對使用兩個字節數組buffer 和 buffer2感到奇怪,當接收到一個自尋址包後,getData()方法返回一個引用,自尋址包的長度是256個字節,如果要輸出所有數據,在輸出完實際數據後會有很多空格,這顯然是不合理的,所以我們必須去掉這些空格,因此我們創建一個小的字節數組buffer2,buffer2的實際長度就是數據的實際長度,通過調用DatagramPacket's getLength()方法來得到這個長度。從buffer 到 buffer2快速復制getLength()的長度的方法是調用System.arraycopy()方法。

  List7 MCServer的源代碼顯示了服務程序是怎樣工作的。

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創建了一個MulticastSocket對象,由於他是DatagramPacket對象的一部分,所以他沒有綁定端口號,DatagramPacket有多點傳送組的IP地址(231.0.0.0),一旦創建DatagramPacket對象,MCServer就進入一個發送30000條的文本的循環中,對文本的每一行均要創建一個字節數組,他們的引用均存儲在前面創建的DatagramPacket對象中,通過send()方法,自尋址包發送給所有的組成員。

  在編譯了MCServer 和 MCClIEnt後,通過輸入Java MCServer開始運行MCServer,最後再運行一個或多個MCClIEnt。

  結論

  本文通過研究套接字揭示了Java的網絡API的應用方法,我們介紹了套接自的慨念和套接字的組成,以及流套接字和自尋址套接字,以及如何使用InetAddress, Socket, ServerSocket, DatagramPacket, DatagramSocket和MulticastSocket類。在完成本文後就可以編寫基本的底層通訊程序。

  1. 上一頁:
  2. 下一頁:
Copyright © 程式師世界 All Rights Reserved