Java实现单播,组播,广播

单播、组播、广播介绍:https://blog.csdn.net/ahou2468/article/details/86526509

目录

 

1.单播、组播、广播关键类说明

2.单播和广播的具体实现

2.1定义套接字管理类

2.2单播或者广播发送数据包类

2.3.单播或者广播接收数据包监听

3.组播的具体实现

3.1定义套接字管理类

3.2组播发送数据包类

3.3组播接收数据包监听


1.单播、组播、广播关键类说明

DatagramSocket:此类表示用于发送和接收数据报包的套接字。数据报套接字是包传递服务的发送或接收点。在数据报套接字上发送或接收的每个数据包都是单独寻址和路由的。从一台机器发送到另一台机器的多个数据包的路由可能不同,并且可能以任何顺序到达。

在可能的情况下,新构造的DatagramSocket启用了So_Broadcast Socket选项,以允许传输广播数据报。为了接收广播数据包,数据报套接字应该绑定到通配符地址。在某些实现中,当数据报套接字绑定到更具体的地址时,也可能接收广播数据包。

示例:DatagramSocket s=new DatagramSocket(null);s.bind(new InetSocketAddress(8888));相当于:DatagramSocket s=new DatagramSocket(8888);这两种情况都将创建一个可以在UDP端口8888上接收广播的DatagramSocket。

注意:DatagramSocket主要用于单播和广播的套接字;

DatagramPacket:此类表示数据报包,用于发送和接收信息的载体。
数据包用于实现无连接数据包传递服务。每个消息都是基于包中包含的信息从一台机器路由到另一台机器的。从一台机器发送到另一台机器的多个数据包的路由可能不同,并且可能以任何顺序到达。不保证包的传送。

MulticastSocket:多播(组播)数据报套接字类对于发送和接收IP多播(组播)数据包很有用。多播(组播)套接字是一个(UDP)数据报套接字,具有附加的功能,可以加入Internet上其他多播(组播)主机的“组”。
多播(组播)组由D类IP地址和标准UDP端口号指定。D类IP地址的范围为224.0.0.0到239.255.255.255(含)。地址224.0.0.0是保留的,不应使用。

当一个人向多播组发送消息时,所有订阅该主机和端口的接收者都会接收该消息(在数据包的生存时间范围内,请参见下文)。套接字不需要是多播组的成员就可以向其发送消息。
当一个套接字订阅一个多播组/端口时,它接收由其他主机发送到该组/端口的数据报,以及该组和端口的所有其他成员。套接字通过leaveGroup(InetAddress addr)方法放弃组中的成员身份。多个多播套接字可以同时订阅多播组和端口,它们都将接收组数据报。

当前不允许小程序(applets)使用多播套接字。

注意:MulticastSocket用于组播的套接字

InetAddress:此类表示Internet协议(IP)地址。
IP地址是由IP使用的32位或128位无符号数字,这是一个较低级别的协议,在该协议上构建诸如UDP和TCP等协议。IP地址体系结构由 RFC 790: Assigned NumbersRFC 1918: Address Allocation for Private InternetsRFC 2365: Administratively Scoped IP Multicast, and RFC 2373: IP Version 6 Addressing Architecture定义。InetAddress的实例由一个IP地址和它相应的主机名组成(取决于它是用主机名构造的,还是已经执行了反向主机名解析)。

2.单播和广播的具体实现

2.1定义套接字管理类

a.创建套接字DatagramSocket,并制定本地绑定的端口号

socket = new DatagramSocket(Constants.UNICAST_PORT);

/**
 * 单播或者广播管理类
 */

public class Unicast {
    //单播或者广播socket
    private DatagramSocket socket;

    private static final Unicast unicast = new Unicast();

    private Unicast(){
        try {
            socket = new DatagramSocket(Constants.UNICAST_PORT);
        } catch (SocketException e) {
            e.printStackTrace();
        }
    }

    public static Unicast getUnicast(){
        return unicast;
    }
    public DatagramSocket getSocket(){
        return socket;
    }

    /**
     * 释放资源
     */
    public void free(){
        if(socket != null){
            socket.close();
            socket = null;
        }
    }
}

2.2单播或者广播发送数据包类

广播地址应用于网络内的所有主机
1)受限广播
它不被路由发送,但会被送到相同物理网络段上的所有主机
IP地址的网络字段和主机字段全为1就是地址255.255.255.255
2)直接广播
网络广播会被路由,并会发送到专门网络上的每台主机
IP地址的网络字段定义这个网络,主机字段通常全为1,如 192.168.10.255

单播地址:具体要发送的目的IP地址;

a.创建数据包,指定发送的内容和地址,单播或者广播地址

DatagramPacket datagramPacket = new DatagramPacket(data,
                    data.length, 单播或者组播地址,
            Constants.UNICAST_PORT);

b.调用套接字发送数据包

Unicast.getUnicast().getSocket().send(datagramPacket);

public class SignInAndOutReq extends JobHandler(Thread){
    private String command;

    public SignInAndOutReq(Handler handler){
        super(handler);
    }

    public void setCommand(String command){

        this.command = command;
    }

    @Override
    public void run() {
        if(command != null){
            byte[] data = command.getBytes();
            if(Command.DISC_REQUEST.equals(command)){
                data = (command+IPUtil.getLocalIPAddress()).getBytes();
            }
            DatagramPacket datagramPacket = new DatagramPacket(data,
                    data.length, 单播或者广播地址,
            Constants.UNICAST_PORT);
            try {
                Unicast.getUnicast().getSocket().send(datagramPacket);
            } catch (IOException e) {
                e.printStackTrace();
            }

            if(command.equals(Command.DISC_REQUEST)){
                sendMsg2MainThread();
            }else if(command.equals(Command.DISC_LEAVE)){
                setCommand(Command.DISC_REQUEST);
            }
        }
    }

    private void sendMsg2MainThread(){
        Message message = new Message();
        message.what = IntercomService.DISCOVERING_SEND;
        handler.sendMessage(message);
    }
}

2.3.单播或者广播接收数据包监听

a.设置接收缓冲区
byte[] receivedData = new byte[512];
DatagramPacket datagramPacket = new DatagramPacket(receivedData, receivedData.length);
b.调用套接字接收数据报文监听,等待接收数据包
 Unicast.getUnicast().getSocket().receive(datagramPacket);

c.程序退出以后释放资源,调用free()方法;

public class Receiver extends JobHandler(Thread) {

    public Receiver(Handler handler){
        super(handler);
    }

    @Override
    public void run() {
        while (true)
        {
            //设置接收缓冲区
            byte[] receivedData = new byte[512];
            DatagramPacket datagramPacket = new DatagramPacket(receivedData, receivedData.length);
            // 接收数据报文
            try {
                Unicast.getUnicast().getSocket().receive(datagramPacket);
            } catch (IOException e) {
                e.printStackTrace();
            }
            // 判断数据报文类型,并做相应处理
            if(datagramPacket.getLength() == Command.DISC_REQUEST.getBytes().length
                    || datagramPacket.getLength() == Command.DISC_RESPONSE.getBytes().length
                    || datagramPacket.getLength() == Command.DISC_LEAVE.getBytes().length){
                handleCommandData(datagramPacket);
            }else{
                handleOptData(datagramPacket);
            }
        }
    }
     @Override
    public void free() {
//        Multicast.getMulticast().free();
        Unicast.getUnicast().free();
    }
}

3.组播的具体实现

3.1定义套接字管理类

a.创建组播套接字,绑定本地端口

multicastSocket = new MulticastSocket(Constants.MULTI_BROADCAST_PORT);

b.创建InetAddress对象,使用组播地址,多播(组播)IP地址就是D类IP地址,即224.0.0.0至239.255.255.255之间的IP地址。

inetAddress = InetAddress.getByName(Constants.MULTI_BROADCAST_IP);

c.加入组播地址

multicastSocket.joinGroup(inetAddress);

当主机不想接收组播信息时,则移除组播地址并关闭套接字

multicastSocket.leaveGroup(inetAddress);
multicastSocket.close();

/**
 * 组播管理类
 */
public class Multicast {
    //组播Socket
    private MulticastSocket multicastSocket;
    //IPV4地址
    private InetAddress inetAddress;

    private static final Multicast multicast = new Multicast();

    private Multicast(){
        try {
            inetAddress = InetAddress.getByName(Constants.MULTI_BROADCAST_IP);
            multicastSocket = new MulticastSocket(Constants.MULTI_BROADCAST_PORT);
            multicastSocket.setLoopbackMode(true);
            multicastSocket.joinGroup(inetAddress);
            multicastSocket.setTimeToLive(4);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    public static Multicast getMulticast(){
        return multicast;
    }

    public MulticastSocket getMulticastSocket(){
        return multicastSocket;
    }

    public InetAddress getInetAddress(){
        return inetAddress;
    }

    public void free(){
        if(multicastSocket != null){
            try {
                multicastSocket.leaveGroup(inetAddress);
                multicastSocket.close();
                multicastSocket = null;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

3.2组播发送数据包类

a.创建数据包,指定发送的内容和地址,使用组播地址

DatagramPacket datagramPacket = new DatagramPacket(data, data.length,

Multicast.getMulticast().getInetAddress(), //组播地址

Constants.MULTI_BROADCAST_PORT);

b.套接字发送数据包

Multicast.getMulticast().getMulticastSocket().send(datagramPacket);

3.3组播接收数据包监听

a.设置接收缓冲区
DatagramPacket sendPacket = new DatagramPacket(feedback, feedback.length,
                    packet.getAddress(), Constants.MULTI_BROADCAST_PORT);

b.套接字接收数据报文监听,等待接收数据包
Multicast.getMulticast().getMulticastSocket().send(sendPacket);

你可能感兴趣的:(单播,组播,广播)