Java数据报编程之组播
2010-03-16 23:57
363 查看
转自其他网站
核心提示:在信息时代,网络技术应用已经很普通。其中很多应用都依赖于从一个主机向多个主机或者从多个主机向多个主机发送同一信息的能力,在Internet
上分发的数目可能达数十万台,这些都需要更高的带宽,并且大大超出了单播的能力。一种能最大限度地利用现有带宽的重
在信息时代,网络技术应用已经很普通。其中很多应用都依赖于从一个主机向多个主机或者从多个主机向多个主机发送同一信息的能力,在Internet
上分发的数目可能达数十万台,这些都需要更高的带宽,并且大大超出了单播的能力。一种能最大限度地利用现有带宽的重要技术是IP
组播。
1
.IP
组播技术的概念
IP
组播技术,是一种允许一台或多台主机(组播源)发送单一数据包到多台主机(一次的,同时的)的TCP/IP
网络技术,
是一点对多点的通信。在网络多媒体广播的应用中,当需要将一个节点的信号传送到多个节点时,无论是采用重复点对点通信方式,还是采用广播方式,都会严重浪费网络带宽,只有组播才是最好的选择。组播能使一个或多个组播源只把数据包发送给特定的组播组,而只有加入该组播组的主机才能接收到数据包。
2
.IP
组播地址
IP
组播通信依赖于IP
组播地址,在IPv4
中它是一个D
类IP
地址,范围从224.0.0.0
到239.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"
);
1444f
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
中进行组播编程有两个特点,
一是使用Java
的MulticastSocket
类,
二是使用组播地址配置MulticastSocket
实例.
数据报编程的全部内容已结束,
如果要改进,
可以在两个方面进行,
一个是改善传输的可靠性方面,
一个是采用数据收发的异步方面,
因为在J2SDK1.4
中MulticastSocket
类增加了方法getChannel().
核心提示:在信息时代,网络技术应用已经很普通。其中很多应用都依赖于从一个主机向多个主机或者从多个主机向多个主机发送同一信息的能力,在Internet
上分发的数目可能达数十万台,这些都需要更高的带宽,并且大大超出了单播的能力。一种能最大限度地利用现有带宽的重
在信息时代,网络技术应用已经很普通。其中很多应用都依赖于从一个主机向多个主机或者从多个主机向多个主机发送同一信息的能力,在Internet
上分发的数目可能达数十万台,这些都需要更高的带宽,并且大大超出了单播的能力。一种能最大限度地利用现有带宽的重要技术是IP
组播。
1
.IP
组播技术的概念
IP
组播技术,是一种允许一台或多台主机(组播源)发送单一数据包到多台主机(一次的,同时的)的TCP/IP
网络技术,
是一点对多点的通信。在网络多媒体广播的应用中,当需要将一个节点的信号传送到多个节点时,无论是采用重复点对点通信方式,还是采用广播方式,都会严重浪费网络带宽,只有组播才是最好的选择。组播能使一个或多个组播源只把数据包发送给特定的组播组,而只有加入该组播组的主机才能接收到数据包。
2
.IP
组播地址
IP
组播通信依赖于IP
组播地址,在IPv4
中它是一个D
类IP
地址,范围从224.0.0.0
到239.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"
);
1444f
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
中进行组播编程有两个特点,
一是使用Java
的MulticastSocket
类,
二是使用组播地址配置MulticastSocket
实例.
数据报编程的全部内容已结束,
如果要改进,
可以在两个方面进行,
一个是改善传输的可靠性方面,
一个是采用数据收发的异步方面,
因为在J2SDK1.4
中MulticastSocket
类增加了方法getChannel().
相关文章推荐
- Java数据报编程之组播 选择自 keepeye 的 Blog
- Java数据报编程之概说
- Java数据报编程之广播
- 【网络编程2】Java数据报套接字
- Java网络编程之组播小案例
- Java 网络编程(六) 使用无连接的数据报(UDP)进行通信
- Java网络编程之组播小案例
- Java网络编程——13.IP组播
- JAVA 网络编程(5) SOCKET UDP 单播和组播,以及组播其他机器收不到报文的解决方法
- 【网络编程3】Java组播套接字
- Java 网络编程(六) 使用无连接的数据报(UDP)进行通信
- Java数据报编程之单播
- Java 网络编程(六) 使用无连接的数据报(UDP)进行通信
- Java UDP网络编程 - 最简单示例
- Java网络编程从入门到精通(18):Socket类的getter和setter方法(2)
- 一起Talk Android吧(第二十三回:Java多线程编程一)
- 网络编程_概念_网络_端口_URL_TCP_UDPJAVA184
- 面向GC的Java编程(转)
- Java网络编程之网络基础
- JAVA常用API或编程工具002---SpringSource Tool Suite:基于Eclipse的Spring应用开发环境