JDK7新特性:MulticastChannel实现非阻塞式组播通信


         一般情况下,我们可以结合利用java.net.MulticastSocket和java.net.DatagramPacket对象来实现组播通信功能。但这在要求满足实时通信的情况下时,则显然有问题。主要体现在:如果没有数据报达到时,MulticastSocke对象调用receive()和send()方法进行收发数据报时,将一直处于阻塞状态,严重影响了后续操作。
        在此之前,解决上述问题的一个方案是利用多线程技术,将接收和发送操作放在不同的线程对象中进行,但这在高交互的场景下时会带来线程开销问题。
        不过利用java.nio.channels.MulticastChannel为我们解决了后顾之忧,这是在JDK1.7中提供的新特点,它可以使组播通信像单播UDP以及面向TCP连接的Socket通信那样,利用通道机制实现无阻塞式的交互环境。

        java.nio.channels.MulticastChannel 只是一个接口,它不具备任何实现细节。不过JDK1.7利用这个接口扩展了java.nio.channels.DatagramChannel 的职责范围,使这个抽象类保留了实现非阻塞式的单播UDP通信基础上,具备了非阻塞式组播UDP通信的能力。  
        下面的实例将模拟用户群聊天的场景。

 

/**
 * <p>非阻塞模式下的组播用户终端,模拟用户群聊天</p> 
 * @author  <a href="mailto:code727@gmail.com">Daniele</a>
 * @version 1.0.0, 2013-4-15
 * @see    
 * @since   AppDemo1.0.0
 */
public class MulticastUserTerminal {
   
    static CharsetEncoder encoder = Charset.forName("UTF-8").newEncoder();
    static Charset charset = Charset.forName("UTF-8");
    static CharsetDecoder decoder = charset.newDecoder();
   
    public static void main(String[] args) {
       
        // 组播通道
        DatagramChannel channel = null;
        // 组播组
        InetAddress group = null;
       
        try {
           
            /*
             *  创建指定协议的组播通道,
             *  1.INET:IPV4
             *  2.INET6:IPV6
             */
            channel = DatagramChannel.open(StandardProtocolFamily.INET);
           
            /*
             *  setOption(StandardSocketOptions.SO_REUSEADDR, true)
             *  表示允许组播成员绑定到相同的端口上,它必须在绑定bind()前调用。
             *  由于bind()方法内的参数绑定的是当前组成员用于接收数据报的本地端口,
             *  因此如果此终端只用于发送,则将bind()方法的参数设置为null或直接去掉此方法。
             */
            channel.setOption(StandardSocketOptions.SO_REUSEADDR, true).bind(new InetSocketAddress(9527));
           
            // 允许接收自己发送出去的数据报
            channel.setOption(StandardSocketOptions.IP_MULTICAST_LOOP, true);
           
            // 关键点,设置组播通道为非阻塞模式
            channel.configureBlocking(false);
           
            /*
             *  如果组播通道是IPV4协议的,则这里创建的本地网络接口也应该具有此协议,否则为IPV6。
             *  如果通道协议与网络接口的协议不一致,则当通道加入组播组时就会抛出java.lang.IllegalArgumentException
             *  与MulticastSocket类似,在接收数据报之前要将创建的本地网络接口加入到组播组。
             *  如果只用于发送目的,则如下三行代码都不要
             */
            group = InetAddress.getByName("224.1.1.108");
            NetworkInterface networkInterface = NetworkInterface.getByName("net4");
            channel.join(group, networkInterface);
           
            ByteBuffer buffer = ByteBuffer.allocate(8192); 
            InetSocketAddress member = null;
            MulticastPacketSenderThread senderThread = null;
            while (true) {
                /*
                 *  由于前面已调用configureBlocking(false)方法将通道设置为非阻塞式的,
                 *  因此这里对需要对读进行判空。与MulticastSocket类似,
                 *  从组播通道的receive()方法的返回结果中,可以得到当前数据报是哪一个组播成员发送的。
                 */
                if ((member = (InetSocketAddress) channel.receive(buffer)) != null) {
                    buffer.flip();
                    String notice = DateUtils.dateToString(new Date(), DateUtils.DEFAULT_DATETIME_FORMAT)
                            + " - 来自 " + member.getHostName() + "[" + member.getAddress().getHostAddress()
                            + ":" + member.getPort() + "] 的消息:" ;
                    System.out.println(notice);
                    System.out.println(decoder.decode(buffer));
                    buffer.clear();
                }
               
                /*
                 *  由于发送数据来源于键盘输入(阻塞式),因此这里需要用线程来实现无阻塞发送。
                 *  如果数据不是来源于阻塞式的终端,则直接在下面判断send()方法执行后是否返回0即可。
                 */
                if (senderThread == null) {
                    senderThread = new MulticastPacketSenderThread(channel, group, 9527);
                    new Thread(senderThread).start();
                } else {
                   
                    // 当输入"exit"后,结束接收和发送数据报
                    if (senderThread.isStopSend())
                        break;
                }
            }
        } catch (IOException e) {
            e.printStackTrace();
        } finally {
            if (channel != null)
                try {
                    channel.close();
                    System.out.println("关闭组播通道");
                } catch (IOException e) {
                    e.printStackTrace();
                }
        }
    }
}  

 

/**
 * <p>数据报发送线程</p>
 * @author  <a href="mailto:code727@gmail.com">Daniele</a>
 * @version 1.0.0, 2013-4-15
 * @see    
 * @since   AppDemo1.0.0
 */
public class MulticastPacketSenderThread implements Runnable {
   
    private DatagramChannel channel;
   
    /** 发送目标组 */
    private InetAddress group;
   
    /** 目标组成员端口号 */
    private int groupPort;
   
    /** 标识是否结束发送操作 */
    private boolean stopSend;
   
    public MulticastPacketSenderThread(DatagramChannel channel, InetAddress group, int groupPort) {
        this.channel = channel;
        this.group = group;
        this.groupPort = groupPort;
    }
   
    public boolean isStopSend() {
        return stopSend;
    }

    public void run() {
        String inputMessage = "";
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        InetSocketAddress target = new InetSocketAddress(group, groupPort);
        while (!stopSend) {
            try {
                inputMessage = reader.readLine();
                if (!"exit".equalsIgnoreCase(inputMessage.trim()))
                    channel.send(ByteBuffer.wrap(inputMessage.getBytes()), target);
                else
                    stopSend = true;
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
    }
}

 

       在Eclipse等IDE环境中,同时运行多个MulticastUserTerminal 实例后,在控制台中输入发送数据后回车,查看各实例的控制台的输出结果即可。


组播用户组


     图1 多播用户组    



图2 User1的控制台      



图3 User2的控制台

Python 爬虫实战:全球咖啡期货市场数据采集与分析全攻略 通过本项目,我们实现了对全球咖啡期货市场数据的采集、处理和可视化,为市场分析和决策支持提供了数据基础。未来,可以进一步结合机器学习和深度学习技术,对咖啡期货价格进行预测和建模,提高市场分析的准确性和效率。 阅读详情

相关推荐

PaddleOCR实战:从零开始训练自己的OCR模型(附完整代码与数据集处理技巧)

本文提供了一份详尽的PaddleOCR实战指南,手把手教你从零开始训练专属的OCR模型。内容涵盖高质量训练数据的准备与标注技巧、预训练模型的选型对比、关键参数调优策略,并附有完整的代码示例。通过遵循本文的步骤,开发者可以高效构建并优化贴合自身业务场景的高精度OCR模型,实现从数据到部署的全流程掌握。

weixin_29263201的博客 570

java channel使用_java11教程--接口MulticastChannel用法

支持Internet协议(IP)多播的网络通道。IP多播是将IP数据报传输到由单个目标地址标识的零个或多个主机的组的成员。一个通道可以加入多个多播组,并可以在几个interfaces上加入同一个组。 通过在返回的MembershipKey上调用drop方法来删除成员资格。 如果底层平台支持源过滤,则可以使用block和unblock方法来阻止或取消阻止来自特定源地址的多播数据报。成员资格是累积的 ...

weixin_33249666的博客 648

CUDA详细安装及环境配置——环境配置指南 – CUDA+cuDNN+PyTorch 安装

本文详细介绍了如何确定显卡支持的CUDA版本、选择对应的cuDNN版本,并逐步安装CUDA、cuDNN和PyTorch。首先,通过命令行输入nvidia-smi.exe查看显卡支持的CUDA版本。接着,根据CUDA版本选择对应的cuDNN版本并下载。然后,从NVIDIA官方网站下载CUDA安装包,按照提示进行安装,并检查是否安装成功。同样地,下载cuDNN安装包,解压后将文件拷贝到CUDA安装目录中,并通过命令行验证安装是否成功。最后,根据PyTorch官网的指引,选择合适的安装命令进行PyTorch的安装

2501_90350274的博客 5098

NIO 四 通道接口

文章目录一 通道二 通道接口三 接口说明3.1 AutoCloseable3.2 Closeable3.3 Channel2.4 InterruptibleChannel2.5 ReadableByteChannel2.6 ScatteringByteChannel2.7 WritableByteChannel2.8 GatheringByteChannel2.9 ByteChannel2.10 SeekableByteChannel2.11 AsynchronousChannel2.12 Asynchro

o983950935的博客 549

出现Command ‘vim‘ is available in the following places,vim: command not found等解决方法

内置命令无法识别,说明系统变量有误,导致无法识别,既然系统变量有误,将其注释或者更改为正确的即可,但是现在打不开,又怎么注释掉。替换vim来打开编辑,打开之前错误的全局变量文件,发现变量有误,要么注释要么改为。系统变量有全局变量(通过命令行printenv或者echo)和局部变量。对应通过vim修改错误的变量文件,不然source也无法让配置文件生效。本身vim是系统内置的命令,连vim都出现问题。修改为正确的即可,之后还需要重启服务器,使用。之后即可成功,通过即可查看命令是否有写入。...

码农研究僧的博客 5883

LangChain .NET:C#开发者构建AI应用的RAG框架与实战指南

大语言模型(LLM)作为当前人工智能的核心技术,通过深度学习海量文本数据,掌握了强大的语言理解和生成能力。其原理基于Transformer架构,通过自注意力机制捕捉长距离依赖关系,从而实现对复杂语义的建模。这一技术价值在于能够将非结构化的自然语言转化为可计算、可推理的表示,为各类智能应用提供认知基础。在实际工程实践中,LLM常被应用于构建检索增强生成(RAG)系统和AI智能体(Agent)。RAG通过结合外部知识库检索与LLM生成,有效提升了问答的准确性和事实性,是构建企业知识库、智能客服等场景的关键技术。

weixin_42538175的博客 705

java nio MulticastChannel源码分析

package java.nio.channels; import java.net.InetAddress; import java.net.NetworkInterface; import java.io.IOException; import java.net.ProtocolFamily; // javadoc import java.net.StandardProtocolFamily; // javadoc import java.net.StandardS..

今天吃了吗的博客 355

基于Simulink的发动机管理系统中的自适应增压控制系统设计

通过上述详细设计步骤,我们成功开发了一个基于Simulink的自适应增压控制系统。该系统不仅能够实时监测和预测发动机的运行状态,动态调整增压压力目标值,还具备实时监控、故障诊断和保护功能,确保系统的安全性和可靠性。此外,通过仿真实验和硬件在环测试,我们验证了系统的性能,并对其进行了优化,使其能够更好地满足实际应用需求。这个项目展示了如何利用MATLAB/Simulink的强大功能,结合控制理论和工程实践,开发出高效、可靠的自适应增压控制系统。

MHD0815的博客 220

MulticastChanne接口定义

import java.net.InetAddress; import java.net.NetworkInterface; import java.io.IOException; import java.net.ProtocolFamily; // javadoc import java.net.StandardProtocolFamily; // javadoc import java.net.StandardSocketOptions; // j

Donald_Draper的专栏 274

YOLOv8改进 | Neck篇 | Slim-Neck替换特征融合层实现超级涨点 (又轻量又超级涨点)

本文给大家带来的改进机制是Slim-neck提出的Neck部分,Slim-neck是一种设计用于优化卷积神经网络中neck部分的结构。在我们YOLOv8中,neck是连接主干网络(backbone)和头部网络(head)的部分,负责特征融合和处理,以便提高检测的准确性和效率。亲测在小目标检测和大尺度目标检测的数据集上都有大幅度的涨点效果(mAP直接涨了大概有0.4左右。同时本文对Slim-Neck的框架原理进行了详细的分析,不光让大家会添加到自己的模型在写论文的时候也能够有一定的参照。

Snu77的博客 1万+

Parasoft C++Test软件集成测试(部件测试)_实例讲解

本文以一组功能函数组件作为示例,讲解了如何使用C++Test进行软件集成测试。本文的示例比较简单,但是思路、方法和流程都是通用的,希望对大家有所帮助。

文章主要涉及嵌入式软件开发、测试、项目管理等,欢迎交流,共同进步。 733

Java 中的广播和多播

一、介绍 在本文中,我们将描述如何在 Java 中处理一对多(广播)和一对多(多播)通信。本文中概述的广播和多播概念基于 UDP 协议。 我们首先快速回顾一下数据报和广播以及它是如何在 Java 中实现的。我们还研究了广播的缺点并建议多播作为广播的替代方案。 最后,我们通过讨论在IPv4 和 IPv6 中对这两种寻址方法的支持来结束。 2. 数据报回顾 根据数据报的官方定义,“数据报是通过网络发送的独立的、自包含的消息,其到达、到达时间和内容都没有保证”。 在 Java 中,java.n

allway2的博客 4003

【GlobalMapper精品教程】006:Excel表格(.xls)或文本(.txt .csv)坐标文件生成矢量点

原始的坐标数据如下图所示,其中坐标为Lat经度,LNG纬度,均为十进制度的形式,一般软件都支持十进制度的格式,如果不支持,你可以尝试使用度分秒的形式,图中的DDMMSS-LAT为纬度,DDMMSS-LNG为经度。打开globalmapper软件,点击【打开数据文件】,选择坐标数据文件(案例中的数据位配套实验数据包中的data006.rar)气象台站分布点坐标.xls。选择坐标系:本案例数据采用的是经纬度,因此选择Geographic(Latitude/Longitude),基准选择WGS84,点击确定。

智慧空间实验室 2570

自学Java基础系列-Java udp协议实现单播与广播

UDP介绍 UDP是Uesr Datagram Protocol的简称,中文名称为用户数据报(包)协议。它具有几下几个特点: UDP协议是一种面向非连接的协议。 面向非连接指的是在正式通信前不必与对方先建立连接,不管对方状态就直接发送数据。 UDP协议是一种不可靠的协议。 对方是否可以接收到这些数据,UDP协议无法控制,言外之意就是,使用UDP协议在进行通信,有可能导致数据的丢失。 U...

747

ET2012新版免狗免安装绿色软件

ET2012新版免狗免安祖昂绿色软件。,新界面,新视觉,

LinePhone3.2.7(android端最新版本) sip客户端

SIP客户端For android:LinePhone3.2.7(最新版本),官网地址:http://www.linphone.org/

Java7新特性——NIO.2

NIO.2是一组新的类和方法,主要存在于java.nio包内。 主要优点: 它完全取代了java.io.File与文件系统的交互。 它提供了新的异步处理类,让你无需手动配置线程池和其他底层并发控制,便可在后台线程中执行文件和网络I/O操作。 它引入了新的Network-Channel构造方法,简化了套接字(Socket)与通道的编码工作。 文件I/O的基石:Path Path通常代表文件...

周先生丶的博客 1519

假人有限元模型

假人模型,车辆碰撞假人有限元模型,适合做乘员安全的研究者利用

java多播_Java多播监听和IGMP

我有一个让我发疯的问题!无论是设计方面还是技术方面。 我需要收听大量的多播地址。我监控/收集的每个项目分为3组。我已经走上了让一个进程旋转100个线程的道路。每个线程使用2个端口和3个地址/组。 (其中2个组在同一个端口上)我正在为每个端口使用MulticastChannel,并使用SELECT监视数据。 (我使用过数据报,但发现NIO MulticastChannel要好得多)。 无论如何,我看...

weixin_31497453的博客 319

复分析 阿尔福斯(Ahlfors) 第三版答案 英文

答案分为十章,有部分习题没有答案,全英文复分析阿尔福斯(Ahlfors) 第三版答案

java 非阻模式_java 阻塞模式与非阻塞模式

packageconcurrentTest;importjava.io.BufferedReader;importjava.io.IOException;importjava.io.InputStreamReader;importjava.io.PrintWriter;importjava.net.ServerSocket;importjava.net.Socket;importjava.net....

weixin_36368715的博客 384

Java 网络编程 —— 非阻塞式编程

在生活中,最常见的阻塞现象是公路上汽车的堵塞。汽车在公路上快速行驶,如果前方交通受阻,就只好停下来等待,等到公路顺畅,才能恢复行驶。线程在运行中也会因为某些原因而阻塞。所有处于阻塞状态的线程的共同特征:放弃 CPU,暂停运行,只有等到导致阻塞的原因消除,才能恢复运行,或者被其他线程中断该线程会退出阻塞状态,并且抛出 InterruptedException线程执行了方法,线程放弃 CPU,睡眠 n ms,然后恢复运行。

低吟不作语的博客 1169

【网络编程】java udp用MulticastSocket实现组播发送和接收数据

关于网络传播的介绍组播代码-发送数据报总结代码2 使用数据报接收其他用户发送的数据 关于网络传播的介绍 网络数据传播按照接收者的数量,可分为以下3种方式。 ·单播:提供点对点的通信。发送者每次发送的数据有着唯一的目的地址,只被一个接收者接收。 ·广播:发送者每次发送的数据可以被传播范围内的所有接收者接收。电视台就采用广播方式。从电视台发射的信号被发送到传播范围内的每个点。不管电视机有没有打开,信号都能到达每台电视机。IP支持广播,但是由于广播会大大增加网络的数据流量,因此对广播的使用作了严格的限制。路由器.

qq_41358574的博客 4385

关于Java的MulticastSocket 同时Receive与Send相互不阻塞

关于Java的MulticastSocket 同时Receive与Send相互不阻塞     直接上代码: package org.eyet.net.udp.multicast.test; import java.io.IOException; import java.net.DatagramPacket; import java.net.InetAddress; imp...

EyeT Hexleo 1107

IP组播 MulticastChannel接口 DatagramChannel实现

监听者 1 import java.io.IOException; 2 import java.net.InetAddress; 3 import java.net.InetSocketAddress; 4 import java.net.NetworkInterface; 5 import java.net.StandardProtocolFamily; 6 impo...

weixin_30332241的博客 229

netty系列之:channel和channelGroup

文章目录简介神龙见首不见尾的channelchannel和channelGroupchannelGroup的基本使用将关闭的channel自动移出同时关闭serverChannel和acceptedChannelChannelGroupFuture总结 简介 channel是netty中数据传输和数据处理的渠道,也是netty程序中不可或缺的一环。在netty中channel是一个接口,针对不同的数据类型或者协议channel会有具体的不同实现。 虽然channel很重要,但是在代码中确实很神秘,基本上我们

程序那些事 6995

java socket 收不到数据包,在任何localhost客户端上MulticastSocket都没有收到多播数据包...

Intro有许多关于创建多播发布者和接收者的教程 .我使用了一个发现here的一些修改 .其他几个:请注意,这些教程都非常相似 .Details:服务器在端口 7777 上运行并将数据报发送到 224.0.0.0 (我在多播范围内测试了几个其他的ip: 224.0.0.0 到 239.255.255.255 ,但是这些都不起作用)然后,客户端加入多播组 224.0.0.0 并等待数据包响应(作为线...

weixin_42310891的博客 527

MulticastSocket

MulticastSocket可以将数据报以广播的方式发送到多个客户端。 MulticastSocket有如下3个构造方法 public MulticastSocket():使用本机默认地址,随机端口来创建MulticastSocket对象。 public MulticastSocket(int portNumber):使用本机默认地址,指定端口创建MulticastSocket

Hknock的专栏 3702

java socket 心得,本人今天学习multicastsocket遇到问题的总结

java.net类MulticastSocketjava.lang.Objectjava.net.DatagramSocketjava.net.MulticastSocket--------------------------------------------------------------------------------publicclassMulticastSocketexte...

weixin_34708196的博客 378

JAVA网路编程之UDP组播

简介: 发送者每次发送的数据可以被小组内的所有接收者接收,组播需要在组播路由器(mrouter)的支持下运行,即需要从发送者到接收者之间的路由器的打开支持组播功能。 实现: UDP的组播实现主要依靠两个类: 1:MulticastSocket:组播socket 用于收发数据包 2:DatagramPacket:数据包,更具不同的需要进行不同的初始化,发送的数据包:初始化的时候要(目的In...

weixin_43836806的博客 571
下一篇: 64位系统上使用PLSQL Developer的解决方案
心如止水dy
博客等级 码龄19年 5粉丝 16原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

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

抵扣说明:

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

余额充值