广播和多播-Java(译)

UDP网络通信第二篇,翻译自国外网站。
原文Broadcasting and Multicasting in Java
第一篇是UDP开发入门指南

1.简介

本文主要介绍了如何在Java中实现广播和多播(组播)通信。广播和多播的概念基于UDP协议。
参考文章:单播,组播(多播),广播以及任播
我们首先快速回顾下数据报和广播以及它是在Java中如何实现的。说明了一些广播的缺点,而多播可以作为广播的一种替代方案。
最后,我们在讨论IPv4和IPv6中对这两种寻址方法的支持时得出结论。

2.数据报回顾

根据Java官方定义,“数据报是一种完整独立的信息,通过网络发送的数据报不保证其到达、到达时间和其内容”。
Java包 java.net 包含了通过UDP协议进行通信的两个类DatagramPacketDatagramSocket 。UDP常用在低延迟、不需要可靠性的场景,如音视频流、网络发现(局域网通信的上下线通知)等等。
要了解UDP和数据报的内容,请参考第一篇-UDP开发入门指南-Java

3.广播

广播是one-to-all的一种通信类型,即会向在同一个链路(网络)中的所有节点发送数据报。与点对点(P2P)通信不同,广播并不知道目标主机地址。而是通过广播地址来发送数据报。

按照Ipv4协议,广播地址是一种逻辑地址,与地址关联的,连接到网络的设备能够收到数据报。在示例中,我们使用一个特别的IP地址,255.255.255.255,该地址作为本地网络中的广播地址。

根据定义,连接本地网络和其他网络的路由器并不会将发送给默认广播地址的数据报转发出去。稍后我们将演示如何遍历所有的网卡,并将数据报发给他们各自的广播地址。

首先,我们先演示如何广播一条消息。要实现此功能,我们需要调用socket中的setBroadcast()方法,让它知道数据报需要被广播。

    private static DatagramSocket socket = null;
 
    public static void main((String[] args)) throws IOException {
        broadcast("Hello", InetAddress.getByName("255.255.255.255"));
    }
 
    public static void broadcast(
      String broadcastMessage, InetAddress address) throws IOException {
        socket = new DatagramSocket();
        socket.setBroadcast(true);
 
        byte[] buffer = broadcastMessage.getBytes();
 
        DatagramPacket packet 
          = new DatagramPacket(buffer, buffer.length, address, 4445);
        socket.send(packet);
        socket.close();
    }
}

下面这段代码通过迭代找到所有网卡中对应的广播地址。

List<InetAddress> listAllBroadcastAddresses() throws SocketException {
    List<InetAddress> broadcastList = new ArrayList<>();
    Enumeration<NetworkInterface> interfaces 
      = NetworkInterface.getNetworkInterfaces();
    while (interfaces.hasMoreElements()) {
        NetworkInterface networkInterface = interfaces.nextElement();
 
        if (networkInterface.isLoopback() || !networkInterface.isUp()) {
            continue;
        }
 
        networkInterface.getInterfaceAddresses().stream() 
          .map(a -> a.getBroadcast())
          .filter(Objects::nonNull)
          .forEach(broadcastList::add);
    }
    return broadcastList;
}

一旦得到广播地址列表,我们就可以执行broadcast() method的代码,根据不同的广播地址发送一条广播消息。。

接受广播消息不需要特别的代码。可以复用UDP开发指南中的代码(待翻译)
原文A Guide To UDP in Java

4.多播(组播)

广播是向本地网络中的所有节点发给广播消息,而不管该节点是否需要,所以效率不高,浪费资源。

多播解决了该问题,它只向感兴趣的节点发送消息。多播基于组概念,一个多播地址代表一个组。

在IPv4地址中, 224.0.0.0 到 239.255.255.255之间的地址可以作为多播地址。只有订阅组的节点才能接受组数据报。

多播使用D类地址。因此,如果从首位开始到第4位是“1110”,就可以认为是多播地址。而剩下的28位可以成为多播的组编号。
---《图解TCP/IP》

在Java中,MulticastSocket 是用来接受发往多播地址的数据报。下面的例子演示了如何使用 MulticastSocket:

public class MulticastReceiver extends Thread {
    protected MulticastSocket socket = null;
    protected byte[] buf = new byte[256];
 
    public void run() {
        socket = new MulticastSocket(4446);
        InetAddress group = InetAddress.getByName("230.0.0.0");
        socket.joinGroup(group);
        while (true) {
            DatagramPacket packet = new DatagramPacket(buf, buf.length);
            socket.receive(packet);
            String received = new String(
              packet.getData(), 0, packet.getLength());
            if ("end".equals(received)) {
                break;
            }
        }
        socket.leaveGroup(group);
        socket.close();
    }
}

MulticastSocket绑定端口后,调用joinGroup()方法,以多播地址作为参数。要接收该组的数据报必须调用此方法。leaveGroup()方法是离开组。
下面的代码展示了如何向多播地址发送消息。

public class MulticastPublisher {
    private DatagramSocket socket;
    private InetAddress group;
    private byte[] buf;
 
    public void multicast(
      String multicastMessage) throws IOException {
        socket = new DatagramSocket();
        group = InetAddress.getByName("230.0.0.0");
        buf = multicastMessage.getBytes();
 
        DatagramPacket packet 
          = new DatagramPacket(buf, buf.length, group, 4446);
        socket.send(packet);
        socket.close();
    }
}

5.广播和IPv6

IPv4支持三种类型的编址:单播、广播和多播。理论上,多播是一对所有的通信,来自某一设备的数据报可以发往整个网络中可到达的所有节点。

由于显而易见的原因,因此IPv4广播的范围显着缩小。
多播虽然也是广播的一种更好的替代方案,但在很晚的时候才出现,因此在采用方面落后。

Ipv6中,已经强制要求多播支持,并且没有明确的广播概念。在IPv6中,多播已得到扩展和改进。因此,因此现在可以通过某种形式的多播来实现所有广播功能。

在Ipv6中,IP地址的最左边的几位用来决定其类型。对于多播地址,其前八位都是1,例如 FF00::/8。另外113-116 代表地址的范围,可以代表如下四种的某一种:全球、本地点、本地链路、本地节点

除了单播和多播,Ipv6还支持任播(anycast)。任播可以将包发给组内的任一成员,而不必发送给本组的所有成员。

6.总结

在本文中,我们研究了UDP协议中的one-to-all和one-to-many的通信类型的概念,并给出了Java中的实现代码。

最后,我们探讨了在IPv4和Ipv6的支持情况。

所有例子均可找到 over on Github.

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 203,324评论 5 476
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 85,303评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 150,192评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,555评论 1 273
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,569评论 5 365
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,566评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 37,927评论 3 395
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,583评论 0 257
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 40,827评论 1 297
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,590评论 2 320
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,669评论 1 329
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,365评论 4 318
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 38,941评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,928评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,159评论 1 259
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 42,880评论 2 349
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,399评论 2 342