【Java例子程序】指定源组播

概述

因公司业务需要使用到指定源组播。经过一番测试,完成了相关功能的小Demo,废话不多说,直接上代码。

开发环境

操作系统:Windows
开发工具:IntelliJ IDEA
JDK:OpenJDK 19.0.1

运行环境

操作系统:中标麒麟V5U2
JDK:java-11-openjdk-devel

发送端

import java.io.IOException;
import java.net.*;

public class MulticastSender {
    
    
    private static void usage() {
    
    
        System.out.println("Usage: java MulticastSender.java address port text");
    }

    public static void main(String[] args) throws IOException, InterruptedException {
    
    
        String host = "",text = "";
        int port = -1;
        if(args.length < 3) {
    
    
            usage();
            return ;
        }else{
    
    
            host = args[0];
            port = Integer.parseInt(args[1]);
        }

        String[] parts = host.split("\\.");
        if(parts.length != 4) {
    
    
            System.out.println("非法地址格式,请重新输入");
            return ;
        }else{
    
    
            int f = Integer.parseInt(parts[0]);
            if(f < 224 || f > 239) {
    
    
                System.out.println("非组播地址格式,请重新输入");
                return ;
            }
        }

        if(port <=0 || port > 65535) {
    
    
            System.out.println("非法端口数值,请重新输入");
            return ;
        }

        text = args[2];
        if(text.isEmpty()) {
    
    
            System.out.println("请输入需要发送的内容");
            return;
        }

        MulticastSocket socket = new MulticastSocket();
        InetSocketAddress isa = new InetSocketAddress(InetAddress.getByName(host), port);
        NetworkInterface ni = NetworkInterface.getByInetAddress(InetAddress.getByName("192.168.1.4"));
        socket.joinGroup(isa, null);
        socket.setTimeToLive(5);
        DatagramPacket dp = new DatagramPacket(text.getBytes(),text.length(), isa);
        while(true) {
    
    
            System.out.println("Sending Data...");
            socket.send(dp);
            Thread.sleep(1000);
        }
    }
}

接收端

import java.io.IOException;
import java.net.*;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;
import java.nio.channels.MembershipKey;
import java.nio.channels.MulticastChannel;

/**
 * 该程序在Linux平台下测试通过,但是Windows收不到Linux发出的数据
 */
public class SpecialMulticastReceiver {
    
    
    private static void usage() {
    
    
        System.out.println("Usage: java SpecialMulticastReceiver.java address port");
    }

    public static void main(String[] args) throws IOException, InterruptedException {
    
    
        String host = "";
        int port = -1;
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        //byte buffer[] = new byte[1024];
        if(args.length < 2) {
    
    
            usage();
            return ;
        }else{
    
    
            host = args[0];
            port = Integer.parseInt(args[1]);
        }

        String[] parts = host.split("\\.");
        if(parts.length != 4) {
    
    
            System.out.println("非法地址格式,请重新输入");
            return ;
        }else{
    
    
            int f = Integer.parseInt(parts[0]);
            if(f < 224 || f > 239) {
    
    
                System.out.println("非组播地址格式,请重新输入");
                return ;
            }
        }

        if(port <=0 || port > 65535) {
    
    
            System.out.println("非法端口数值,请重新输入");
            return ;
        }

        InetSocketAddress isa = new InetSocketAddress(port);
        NetworkInterface ni = NetworkInterface.getByInetAddress(InetAddress.getByName("192.168.1.4"));
        DatagramChannel dc = DatagramChannel.open(StandardProtocolFamily.INET)
                .setOption(StandardSocketOptions.SO_REUSEADDR, true)
                .setOption(StandardSocketOptions.IP_MULTICAST_LOOP, false)
                .bind(isa)
                .setOption(StandardSocketOptions.IP_MULTICAST_IF, ni);

        //添加指定源
        MembershipKey key = dc.join(InetAddress.getByName(host), ni, InetAddress.getByName("192.168.1.4"));
        MembershipKey key1 = dc.join(InetAddress.getByName(host), ni, InetAddress.getByName("192.168.1.5"));
        MulticastChannel mc = key.channel();
        while(true) {
    
    
            //接收数据
            while((((DatagramChannel)mc).receive(buffer))!= null) {
    
    
                buffer.flip();
                System.out.println("Data: " + new String(buffer.array()));
                buffer.clear();
            }
        }
    }
}

问题&回答

Q: 接收端的代码在Windows平台死活收不到数据,不知道什么情况。但是在Linux平台则一切正常,有知道的小伙伴,希望解答一下哈。
A:

Q:在中标麒麟下添加指定源地址,当数量达到10个就会出现添加失败的情况。
A:修改net.ipv4.igmp_max_msf属性,其他linux内核应该也能通用。
修改代码如下:

echo "net.ipv4.igmp_max_msf=128" >> /etc/sysctl.conf
sysctl -p

参考链接

【技术】组播技术详解系列——组播基础
MulticastChannel (Java SE 11 & JDK 11 )

猜你喜欢

转载自blog.csdn.net/qq_38189542/article/details/129018228
今日推荐