UDP广播
广播UDP与单播UDP的区别就是IP地址不同,广播使用广播地址255.255.255.255,将消息发送到在同一广播网络上的每个主机。值得强调的是:本地广播信息是不会被路由器转发。当然这是十分容易理解的,因为如果路由器转发了广播信息,那么势必会引起网络瘫痪。这也是为什么IP协议的设计者故意没有定义互联网范围的广播机制。
广播地址通常用于在网络游戏中处于同一本地网络的玩家之间交流状态信息等。广播就不在写演示程序了,读者可以将ECHO程序的ip地址改为广播地址即可。
其实广播顾名思义,就是想局域网内所有的人说话,但是广播还是要指明接收者的端口号的,因为不可能接受者的所有端口都来收听广播。
服务段代码:
- import java.io.IOException;
- import java.net.DatagramPacket;
- import java.net.DatagramSocket;
- import java.net.InetAddress;
- import java.net.SocketException;
- import java.net.UnknownHostException;
- import java.text.SimpleDateFormat;
- import java.util.Date;
- import java.util.Timer;
- public class UdpSend {
- public void sendData()throws SocketException,
- UnknownHostException{
- DatagramSocket ds = new DatagramSocket();// 创建用来发送数据报包的套接字
- String str = "1";
- DatagramPacket dp = new DatagramPacket(str.getBytes(),
- str.getBytes().length,
- InetAddress.getByName("255.255.255.255"), 3001);
- // 构造数据报包,用来将长度为 length 的包发送到指定主机上的指定端口号
- try {
- ds.send(dp);
- } catch (IOException e) {
- e.printStackTrace();
- }
- ds.close();
- }
- public static void main(String[] args) {
- Timer timer = new Timer();
- timer.schedule(new MyTask(), 1000, 1000);
- }
- static class MyTask extends java.util.TimerTask{
- @Override
- public void run() {
- UdpSend tt = new UdpSend();
- Date d = new Date();
- SimpleDateFormat sdf = new SimpleDateFormat("HH:mm:ss");
- String strdate = sdf.format(d);
- String[] classTime = {"17:18:00","17:19:00","17:20:00"};
- for(int i = 0;i<classTime.length;i++){
- if(classTime[i].equals(strdate)){
- try {
- tt.sendData();
- } catch (SocketException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- } catch (UnknownHostException e) {
- // TODO Auto-generated catch block
- e.printStackTrace();
- }
- }
- }
- }
- }
- }
客户单简单代码示例,没有做循环
- package udp;
- import java.net.DatagramPacket;
- import java.net.DatagramSocket;
- public class UdpRecv {
- public static void main(String[] args) throws Exception {
- DatagramSocket ds = new DatagramSocket(3001);// 创建接收数据报套接字并将其绑定到本地主机上的指定端口
- byte[] buf = new byte[1024];
- DatagramPacket dp = new DatagramPacket(buf, 1024);
- ds.receive(dp);
- String strRecv = new String(dp.getData(), 0, dp.getLength()) + " from "
- + dp.getAddress().getHostAddress() + ":" + dp.getPort();
- System.out.println(strRecv);
- ds.close();
- }
- }
UDP多播
同样的UDP多播也要指明接受者的端口号,而且与广播相似的是多播与单播之间的区别还在于地址。ipv4中的多播地址范围是:224.0.0.0到239.255.255.255。
1、IP多播地址和多播组IP多播通信必须依赖于IP多播地址。在IPv4中它是一个D类IP地址,范围从224.0.0.0到239.255.255.255,地址 224.0.0.0 被保留,不应使用。 并被划分为局部链接多播地址、预留多播地址和管理权限多播地址三类。其中,局部链接多播地址范围在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,可限制多播范围。
使用同一个IP多播地址接收多播数据包的所有主机构成了一个主机组,也称为多播组。一个多播组的成员是随时变动的,一台主机可以随时加入或离开多播组,多播组成员的数目和所在的地理位置也不受限制,一台主机也可以属于几个多播组。此外,不属于某一个多播组的主机也可以向该多播组发送数据包。
2、加入或退出多播组
可以通过使用所需端口创建 MulticastSocket,然后调用 joinGroup(InetAddress groupAddr) 方法来加入多播组。
套接字通过 leaveGroup(InetAddress addr) 方法放弃组中的成员资格。
3、发送或接收数据包
当套接字预定多播组/端口时,像所有其他成员一样(组和端口相同),它将接收其他成员发送的数据报。
将消息发送到多播组时,该主机和端口的所有预定接收者都将接收到消息(在数据包的生存范围内)。套接字不必成为多播组的成员即可向其发送消息。
4、多个 MulticastSocket 可以同时预定多播组和端口,并且都会接收到组数据包。
5、不允许 applet 使用多播套接字。
- // 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!
- 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);