Java數據報編程之組播

轉自其他網站



核心提示:在信息時代,網絡技術應用已經很普通。其中很多應用都依賴於從一個主機向多個主機或者從多個主機向多個主機發送同一信息的能力,在Internet 上分發的數目可能達數十萬臺,這些都需要更高的帶寬,並且大大超出了單播的能力。一種能最大限度地利用現有帶寬的重

在信息時代,網絡技術應用已經很普通。其中很多應用都依賴於從一個主機向多個主機或者從多個主機向多個主機發送同一信息的能力,在Internet 上分發的數目可能達數十萬臺,這些都需要更高的帶寬,並且大大超出了單播的能力。一種能最大限度地利用現有帶寬的重要技術是IP 組播。


1 IP 組播技術的概念

IP 組播技術,是一種允許一臺或多臺主機(組播源)發送單一數據包到多臺主機(一次的,同時的)的TCP/IP 網絡技術, 是一點對多點的通信。在網絡多媒體廣播的應用中,當需要將一個節點的信號傳送到多個節點時,無論是採用重複點對點通信方式,還是採用廣播方式,都會嚴重浪費網絡帶寬,只有組播纔是最好的選擇。組播能使一個或多個組播源只把數據包發送給特定的組播組,而只有加入該組播組的主機才能接收到數據包。

2 IP 組播地址

IP 組播通信依賴於IP 組播地址,在IPv4 中它是一個DIP 地址,範圍從224.0.0.0239.255.255.255 ,並被劃分爲局部鏈接組播地址、預留組播地址和管理權限組播地址三類。其中,局部鏈接組播地址範圍在224.0.0.0~224.0.0.255 ,這是爲路由協議和其它用途保留的地址,路由器並不轉發屬於此範圍的IP 包;預留組播地址爲224.0.1.0~238.255.255.255 ,可用於全球範圍(如 Internet )或網絡協議;管理權限組播地址爲239.0.0.0~239.255.255.255 ,可供組織內部使用,類似於私有IP 地址,不能用於Internet ,可限制組播範圍。

3 .組播組

使用同一個IP 組播地址接收組播數據包的所有主機構成了一個主機組,也稱爲組播組。一個組播組的成員是隨時變動的,一臺主機可以隨時加入或離開組播組,組播組成員的數目和所在的地理位置也不受限制,一臺主機也可以屬於幾個組播組。此外,不屬於某一個組播組的主機也可以向該組播組發送數據包。

本文使用MulticastSocket 類的實例編寫組播應用,MulticastSocket 類提供連接和離開組播等操作。

MultiSender 類清單

1.       package  recmail.multiservice;   

2.         

3.       import  java.net.*;   

4.       import  java.io.IOException;   

5.         

6.       /**  

7.        *  該類封裝了MulticastSocket, 完成了MulticastSocket 類實例的創建、初始化功能,  

8.        *  並提供了一個發送數據的接口.  

9.        */   

10.       

11.     public   class  MultiSender {   

12.        public   static   final   int  MultiSender_Port= 4099 ;   

13.        private  MulticastSocket road;   

14.        private  InetAddress ia;   

15.       

16.        public  MultiSender() {   

17.          try  {   

18.       

19.            // 組播地址   

20.           ia = InetAddress.getByName( "239.66.69.18" );   

21.           road =  new  MulticastSocket(MultiSender_Port);   

22.           road.joinGroup(ia);   

23.         }   

24.          catch  (UnknownHostException ex) {   

25.         }   

26.          catch  (IOException ex1) {   

27.         }   

28.       }   

29.        public  InetAddress getInetAddress(){   

30.          return  ia;   

31.       }   

32.        public  MulticastSocket getRoad(){   

33.          return  road;   

34.       }   

35.        public   void  send( byte [] b){   

36.         DatagramPacket dp =  new  DatagramPacket(b,  0 , b.length,   

37.                                                    ia, MultiSender.MultiSender_Port);   

38.          try  {   

39.           road.send(dp);   

40.         }   

41.          catch  (IOException ex) {   

42.           ex.printStackTrace();   

43.         }   

44.       }   

45.     }   

 

ImageServer , 使用上面的類發送文件數據.

1.       package  recmail.multiservice;   

2.       import  java.io.*;   

3.       import  javax.swing.Timer;   

4.       import  java.awt.event.*;   

5.       import  java.awt.image.*;   

6.       import  java.util.*;   

7.       import  java.io.FileFilter;   

8.       import  java.io.FilenameFilter;   

9.         

10.     /**  

11.      *  本類利用MultiSender 類發送文件數據到一個組播組發送數據.  

12.      */   

13.       

14.     public   class  ImageServer   

15.          extends  Thread  implements  ActionListener {   

16.       Timer timer;   

17.       BufferedImage image;   

18.       ArrayList streamfragments;   

19.        int  counter =  0 ;   

20.        byte [] imagebyte;   

21.       ArrayList listener;   

22.       MultiSender sender;   

23.       

24.        public  ImageServer(ArrayList f) {   

25.         timer =  new  Timer( 50 this );   

26.         timer.addActionListener( this );   

27.         listener =  new  ArrayList();   

28.         streamfragments = f;   

29.         sender =  new  MultiSender();   

30.         timer.start();   

31.       }   

32.       

33.        public   void  addDataSwapListener(DataSwapListener dsl) {   

34.         listener.add(dsl);   

35.       }   

36.       

37.        public   void  removeDataSwapListener(DataSwapListener dsl) {   

38.         listener.remove(dsl);   

39.       }   

40.       

41.        private   void  processEvent() {   

42.          for  ( int  i =  0 ; i <  this .listener.size(); i++) {   

43.           DataSwapEvent dse =  new  DataSwapEvent();   

44.           ( (DataSwapListener) this .listener.get(i)).OnDataSendFinished( this , dse);   

45.         }   

46.       }   

47.       

48.        public   void  actionPerformed(ActionEvent e) {   

49.         DataPacket dp =  new  DataPacket(streamfragments.get(counter).toString());   

50.         DataEntry de;   

51.          try  {   

52.           ArrayList al = dp.getDataPackets();   

53.           Thread.sleep( 1000 );   

54.           System.out.println(streamfragments.get(counter).toString());   

55.            for  ( int  i =  0 ; i < al.size(); i++) {   

56.             imagebyte = ( (DataEntry) al.get(i)).getByte();  //(byte[]) al.get(i);   

57.             sender.send(imagebyte);   

58.           }   

59.            this .processEvent();   

60.         }   

61.          catch  (Exception ex) {   

62.           System.out.println(ex);   

63.         }   

64.         counter++;   

65.          if  (counter >= streamfragments.size())   

66.           counter =  0 ;   

67.       }   

68.       

69.        public   void  run() {   

70.          while  ( true ) {   

71.            try  {   

72.              this .sleep( 20 );   

73.           }   

74.            catch  (InterruptedException ex) {   

75.           }   

76.         }   

77.       }   

78.       

79.        public   static   void  main(String[] args) {   

80.         String file[];   

81.         ArrayList al =  new  ArrayList();   

82.         String path =  "E://mzip//" ;    

83.         File f =  new  File(path);   

84.         file = f.list();   

85.          for  ( int  i =  0 ; i < file.length; i++) {   

86.            if  (file[i].endsWith( "jpg" ) || file[i].endsWith( "bmp" ))    

87.             al.add(path + file[i]);   

88.         }   

89.         ImageServer is =  new  ImageServer(al);   

90.         is.start();   

91.       }   

92.     }   

1.       package  recmail.multiservice;   

2.         

3.       import  java.net.*;   

4.       import  java.io.*;   

5.       import  java.awt.image.*;   

6.       /**  

7.        *  該類封裝了MulticastSocket, 完成了MulticastSocket 類實例的創建、初始化功能,  

8.        *  並提供一個接收數據的線程, 在判斷接收完畢後產生事件, 更新UI 顯示.  

9.        *  該類由testFrame 使用.  

10.      */   

11.     public   class  ImageShow   

12.          extends  DataSwapListenerAdapter   

13.          implements  Runnable {   

14.        private  InetAddress ia;   

15.        private   int  port =  4099 ;   

16.        private  MulticastSocket road;   

17.       DataSwapEvent dsevent;   

18.       java.awt.image.BufferedImage bi;   

19.       

20.        public  ImageShow() {   

21.         dsevent =  new  DataSwapEvent( this );   

22.          try  {   

23.           ia = InetAddress.getByName( "239.66.69.18" );   

24.           road =  new  MulticastSocket(port);   

25.           road.joinGroup(ia);   

26.         }   

27.          catch  (IOException ex) {   

28.         }   

29.       }   

30.       

31.        public   void  run() {   

32.          byte [] buffer =  new   byte [DataPacket.DataSwapSize];   

33.         DatagramPacket packet =  new  DatagramPacket(buffer, buffer.length);   

34.         DataPacket dp =  new  DataPacket();   

35.          while  ( true ) {   

36.           packet.setLength(buffer.length);   

37.           System.out.println( "wait .. " );   

38.            try  {   

39.             road.receive(packet);   

40.             dp.Add(packet.getData());   

41.              if  (dp.isFull()) {   

42.               dsevent.setImage(dp.Gereratedata());   

43.                this .processRecvFinishedEvent(dsevent);   

44.               dp =  new  DataPacket();   

45.             }   

46.           }   

47.            catch  (IOException ex) {   

48.             System.out.println(ex);   

49.           }   

50.         }   

51.       }   

52.     }   

接收端界面類:

1.       package  recmail.multiservice;   

2.         

3.       import  javax.swing.*;   

4.       import  java.awt.*;   

5.       import  java.awt.image.*;   

6.         

7.       /**  

8.        *  該類使用ImageShow 更新顯示的圖象.  

9.        */   

10.       

11.     public   class  testFrame   

12.          extends  JApplet   

13.          implements  DataSwapListener {   

14.        private  JPanel root;   

15.       JLabel label;   

16.       JImagePanel ip;   

17.       java.awt.Image bi;   

18.       

19.        public  testFrame() {   

20.         initmain();   

21.       }   

22.       

23.        public   void  init() {   

24.         initmain();   

25.          this .setContentPane(root);   

26.         ImageShow is =  new  ImageShow();   

27.         is.addDataSwapListener( this );   

28.         Thread thread =  new  Thread(is,  "test" );   

29.         thread.start();   

30.       }   

31.       

32.        public   static   void  main(String[] args) {   

33.         testFrame test =  new  testFrame();   

34.         test.go( new  JFrame());   

35.         ImageShow is =  new  ImageShow();   

36.         is.addDataSwapListener(test);   

37.         Thread thread =  new  Thread(is,  "test" );   

38.         thread.start();   

39.       }   

40.       

41.        public   void  go(JFrame frame) {   

42.         frame.setContentPane(root);   

43.         frame.setSize( 300 200 );   

44.         frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);   

45.         frame.validate();   

46.         frame.setVisible( true );   

47.       }   

48.       

49.        public   void  initmain() {   

50.         root =  new  JPanel();   

51.          //label = new JLabel();   

52.         ip =  new  JImagePanel();   

53.         root.setLayout( new  BorderLayout( 5 5 ));   

54.         root.add(ip, BorderLayout.CENTER);   

55.       }   

56.       

57.        public   void  setRefreshImage(java.awt.image.BufferedImage img) {   

58.          this .bi = img;   

59.         ip.setImage(bi);   

60.       }   

61.       

62.        public   void  paint(Graphics g) {   

63.          super .paint(g);   

64.       }   

65.       

66.        public   void  paintComponents(Graphics g) {   

67.          super .paintComponents(g);   

68.         Graphics g1 = root.getGraphics();   

69.         g1.drawImage(bi,  0 0 this );   

70.       }   

71.       

72.        public   void  OnDataSendFinished(Object s, DataSwapEvent e) {   

73.       

74.       }   

75.       

76.        public   void  OnDataRecvFinished(Object s, DataSwapEvent e) {   

77.          this .bi = e.getImage();   

78.         ip.setImage(bi);   

79.         System.out.println( "recv Finished!" );   

80.       }   

81.     }   

到此, 這個多播程序編寫完畢, 通過這個程序可以看出在Java 中進行組播編程有兩個特點, 一是使用JavaMulticastSocket, 二是使用組播地址配置MulticastSocket 實例.

數據報編程的全部內容已結束, 如果要改進, 可以在兩個方面進行, 一個是改善傳輸的可靠性方面, 一個是採用數據收發的異步方面, 因爲在J2SDK1.4MulticastSocket 類增加了方法getChannel().

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章