JAVA基于UDP的多点广播数据报技术的一个实现例子

Open Declarationcom.han.Weather

This is a UDP network program. The following presents a multicast datagram program, which is actually a new technology. The multicast datagram socket class is useful for sending and receiving IP multicast packets. A MulticastSocket is a (UDP) DatagramSocket, with additional capabilities for joining "groups" of other multicast hosts on the internet.

A multicast group is specified by a class D IP address and by a standard UDP port number. Class D IP addresses are in the range 224.0.0.0 to 239.255.255.255, inclusive. The address 224.0.0.0 is reserved and should not be used.

One would join a multicast group by first creating a MulticastSocket with the desired port, then invoking the joinGroup(InetAddress groupAddr) method:

// join a Multicast group and send the group salutations

...

String msg = "Hello";

InetAddress group = InetAddress.getByName("228.5.6.7");

MulticastSocket s = new MulticastSocket(6789);

s.joinGroup(group);

DatagramPacket hi = new DatagramPacket(msg.getBytes(), msg.length(), group, 6789);

s.send(hi);

// get their responses! Normally in another computer(host) who joins in the specific group.

byte[] buf = new byte[1000];

DatagramPacket recv = new DatagramPacket(buf, buf.length);

s.receive(recv);

...

// OK, I'm done talking - leave the group...

s.leaveGroup(group);

When one sends a message to a multicast group, all subscribing recipients to that host and port receive the message (within the time-to-live range of the packet, see below). The socket needn't be a member of the multicast group to send messages to it.

When a socket subscribes to a multicast group/port, it receives datagrams sent by other hosts to the group/port, as do all other members of the group and port. A socket relinquishes membership in a group by the leaveGroup(InetAddress addr) method.

By the way, I'd like to talk about a bit the Datagram communication which is based on UDP, contrast to the TCP based program.

For UDP based program:

In the send part, one uses new DatagramSocket() to create a socket, not binding a port, which instead will be designated by the system automatically. Then, we can usenew DatagramPacket(data, data.length, InetAddress, port) to create a packet. Finally, invokesocket.send(packet) to complete the send part operation.

In the receive part, one uses new DatagramSocket(port) to create a socket, note that we have to bind a port to match the one in the coming packet. Then, we can usenew DatagramPacket(dataBuf, dataBuf.length) to create a packet to hold the incoming packet. Finally, invokesocket.receive(packet) to finalize the receive part operation.

For TCP based program:

There is a clear distinction between the client part and the server part. I mean that in the server part program, there is a socket called ServerScoket, which can be created bynew ServerSocket(port), and wait for its client's request, once it happens, it creates a socket object automatically to connect the client socket by:


 Socket socket=serverSocket.accept()
In which serverSocket is a citation of the object to the class ServerSocket. One should note that the accept() method will block the executing thread until the reception of the client's request. If there is no request received, but the accept() is not blocked, there must be a bug in the program. Normally, this is due to the usage of a port that is occupied at the same time by another program. It is to say that ServerSocket is not successfully binded.

In the client part programming, we should create a socket like this: new Socket(InetAddress server, port) to establish a connection to the server.

Both the server socket object and the client socket object can call the method getOutputStream() and getInputStream(). So these sockets use them to communicate, instead of send() and receive() for the DatagramSocket.

You might think that why there are so detailed procedures to follow. Simply, the response is that it is described and imposed in the API (Application Programming Interface) by Java SUN. We can not create but obey it.

Author:

HAN


package com.han;
import java.net.*;
/**
 * This is a UDP network program.
 * The following presents a multicast datagram program,
 * which is actually a new technology.
 * 
 * The multicast datagram socket class is useful for sending and receiving
 * IP multicast packets. A MulticastSocket is a (UDP) DatagramSocket, 
 * with additional capabilities for joining "groups" of other multicast hosts on the internet.
 * <p>
 * A multicast group is specified by a class D IP address and by a standard UDP port number.
 * Class D IP addresses are in the range 224.0.0.0 to 239.255.255.255, inclusive.
 * The address 224.0.0.0 is reserved and should not be used.
 * <p>
 * One would join a multicast group by first creating a MulticastSocket with the desired port,
 * then invoking the joinGroup(InetAddress groupAddr) method:
 * <p>
 * <code>
 * // join a Multicast group and send the group salutations<p>
 * ...<p>
 * String msg = "Hello";<p>
 * InetAddress group = InetAddress.getByName("228.5.6.7");<p>
 * MulticastSocket s = new MulticastSocket(6789);<p>
 * s.joinGroup(group);<p>
 * DatagramPacket hi = new DatagramPacket(msg.getBytes(), msg.length(), group, 6789);<p>
 * s.send(hi);<p>
 * // get their responses! Normally in another computer(host) who joins in the specific group.<p>
 * byte[] buf = new byte[1000];<p>
 * DatagramPacket recv = new DatagramPacket(buf, buf.length);<p>
 * s.receive(recv); <p>
 * ...<p>
 * // OK, I'm done talking - leave the group...<p>
 * s.leaveGroup(group);<p>
 </code>
 * When one sends a message to a multicast group, all subscribing recipients to that host
 * and port receive the message (within the time-to-live range of the packet, see below). 
 * The socket needn't be a member of the multicast group to send messages to it.
 * <p>
 * When a socket subscribes to a multicast group/port, 
 * it receives datagrams sent by other hosts to the group/port, 
 * as do all other members of the group and port. 
 * A socket relinquishes membership in a group by the leaveGroup(InetAddress addr) method. 
 * 
 * <p>
 * By the way, I'd like to talk about a bit the Datagram communication which based on UDP, 
 * contrast to the TCP based program. 
 * <p>
 * For UDP based program:
 * <p>
 * In the send part, one uses <code>new DatagramSocket()</code> to create a socket, not binding
 * a port, which instead will be designated by the system automatically. Then, we can use <code>
 * new DatagramPacket(data, data.length, InetAddress, port)</code> to create a packet. Finally,
 * invoke <code>socket.send(packet)</code> to complete the send part operation.
 * <p>
 * In the receive part, one uses <code>new DatagramSocket(port)</code> to create a socket, 
 * note that we have to bind a port to match the one in the coming packet.
 * Then, we can use <code>new DatagramPacket(dataBuf, dataBuf.length)</code> to create a packet
 * to stock the coming packet. Finally, invoke <code>socket.receive(packet)</code> 
 * to finalize the receive part operation.
 * 
 * <p>
 * For TCP based program:
 * <p>
 * There is a clear distinction between the client part and the server part. I mean that in the 
 * server part program, there is a socket called ServerScoket, which can be created by <code>
 * new ServerSocket(port)</code>, and wait for its client's request, once it happens, it creates a 
 * socket object automatically to connect the client socket by: <pre><code>
 * Socket socket=serverSocket.accept()</code></pre> 
 * In which <code>serverSocket</code> is a citation of the object to the class ServerSocket. 
 * One should note that the accept() method will block the executing thread until the reception
 * of the client's request. If there is no request received, but the accept() is not blocked, 
 * there must be a bug in the program. Normally, this is due to the usage of a port that is 
 * occupied at the same time by another program. It is to say that ServerSocket is not 
 * successfully binded.
 * <p>
 * In the client part programming, we should create a socket like this: <code>
 * new Socket(InetAddress server, port)</code> to establish a connection to the server.
 * <p>
 * Both the server socket object and the client socket object can call the method getOutputStream()
 * and getInputStream(). So these sockets use them to communicate, instead of send() and receive()
 * for the DatagramSocket.
 * @author HAN
 *
 */
public class Weather extends Thread{
	String weather ="节目预告: 八点有大型晚会,请收听";
	int port =9898;
	InetAddress iaddress;//没法初始化,这里只能声明。因为初始化new对象时要抛出异常所以在成员变量区域是语法通不过的。
	//MulticastSocket socket;
	DatagramSocket socket;
	//在构造方法中初始化成员变量
	Weather(){
		/*try {
			//A multicast group is specified by a class D IP address 
			//and by a standard UDP port number.
			//Class D IP addresses are in the range 224.0.0.0 to 239.255.255.255, inclusive.
			//The address 224.0.0.0 is reserved and should not be used.
			iaddress=InetAddress.getByName("233.0.0.0");
			socket=new MulticastSocket(port);
			socket.setTimeToLive(1);
			socket.joinGroup(iaddress);
		}catch(Exception e){
			e.printStackTrace();
		}*/
		try {
			iaddress=InetAddress.getByName("233.0.0.0");
			socket=new DatagramSocket();
		} catch (SocketException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		} catch (UnknownHostException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
	@Override   //最简单的方法也就是建立一个线程来运行
	public void run(){
		while(true){
			byte[] data=weather.getBytes();
			DatagramPacket packet=new DatagramPacket(data,data.length,iaddress,port);
			// System.out.println(weather);
			System.out.println(new String(data));
			try {
				socket.send(packet);
				sleep(3000);//线程休眠3秒
			} catch (Exception e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
		}
	}
	public static void main(String[] args){
		Weather w=new Weather();
		w.start();
	}
}

package com.han;
import java.awt.BorderLayout;
import java.awt.Color;
import java.awt.event.*;
import java.io.IOException;
import java.net.DatagramPacket;
import java.net.InetAddress;
import java.net.MulticastSocket;
import javax.swing.JButton;
import javax.swing.JFrame;
import javax.swing.JPanel;
import javax.swing.JScrollPane;
import javax.swing.JTextArea;
/**
 * This is the receive part.
 * @author HAN
 *
 */
public class Receive extends JFrame implements Runnable, ActionListener{
	private static final long serialVersionUID = 3362377947503474102L;
	int port=9898;
	InetAddress group;
	MulticastSocket socket; //socket sends and receives the packet.
	DatagramPacket packet;
	JButton ince=new JButton("开始接收");
	JButton stop=new JButton("停止接收");
	JTextArea inceAr=new JTextArea(10,20);
	JTextArea inced=new JTextArea(10,20);
	Thread thread;
	boolean b = false;
//	byte[] buf=new byte[30];
	// If the message is longer than the packet's length, the message is truncated.
	byte[] buf=new byte[1024];
	
	//在构造方法中设置具体参数特性,也就是初始化
	public Receive(){
		super("广播数据报");
		thread=new Thread(this);
		ince.addActionListener(this);
		stop.addActionListener(this);
		inceAr.setForeground(Color.blue);
		JPanel north=new JPanel();
		north.add(ince);
		north.add(stop);
		add(north,BorderLayout.NORTH);
		JPanel center=new JPanel();
		JScrollPane sp=new JScrollPane(inceAr);
		JScrollPane sp2=new JScrollPane(inced);
		inceAr.setLineWrap(true);
		inceAr.setEditable(false);
		inced.setLineWrap(true);
		inced.setEditable(false);
		center.add(sp);
		center.add(sp2);
		add(center,BorderLayout.CENTER);
		pack(); //JFrame inherited from Window
		validate();
		setVisible(true);
		setDefaultCloseOperation(EXIT_ON_CLOSE);
		try {
			socket=new MulticastSocket(port);
			//A multicast group is specified by a class D IP address 
			//and by a standard UDP port number.
			//Class D IP addresses are in the range 224.0.0.0 to 239.255.255.255, inclusive.
			//The address 224.0.0.0 is reserved and should not be used.
			group=InetAddress.getByName("233.0.0.0");
			socket.joinGroup(group); 
			packet=new DatagramPacket(buf,buf.length);
			
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
		
	}
	@Override
	public void run(){
		while(true){
			try {
				socket.receive(packet);
			} catch (IOException e) {
				// TODO Auto-generated catch block
				e.printStackTrace();
			}
//			String message=new String(buf);
			String message=new String(packet.getData(),0,packet.getLength());//very important !!
//			System.out.println(message.length());
			inceAr.setText("正在接受的内容: \n"+message);
			inced.append(message+"\n");
			if(b==true){
				break;
			}
		}
	}
	public void actionPerformed(ActionEvent e){
		Object object=e.getSource();
		if(object==ince){
			//If this thread is already on the state "run", do nothing.
			if(!thread.isAlive()){
				thread=new Thread(this);
				thread.start();
				ince.setBackground(Color.red);
				stop.setBackground(Color.yellow);
				b=false;
			}	
		}
		if(object==stop){
			ince.setBackground(Color.yellow);
			stop.setBackground(Color.red);
			b=true;
		}
	}
	public static void main(String[] args){
		@SuppressWarnings("unused")
		Receive rec=new Receive();
//		rec.setSize(460, 200);//提供了额外设置窗体大小的方式
	}
}

  • 2
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值