如何使用Java MulicastSocket (UDP)?

How to use Java MulicastSocket (UDP)?

我开发客户端-服务器应用程序,实时工作。服务器和客户端通过小消息交换,所以我选择 UDP 作为我的体系结构(正如网络中许多文章所建议的那样)。 使用默认的 java 的 DatagramSocket/DatagramPacket 来组织我想要的所有东西对我来说不是问题,但是当我阅读文档时,我看到了 "MulticastSocket" 的机会。 但我完全不清楚:用户端的 MutlicastSocket 如何知道连接到哪里? (服务器的public IP/port)。真的,正如这个官方javatutorial所示。 MulticastSocket 创建如下:

MulticastSocket socket = new MulticastSocket(4446);
InetAddress group = InetAddress.getByName("203.0.113.0");
socket.joinGroup(group);

并且没有关于public服务器IP和端口的任何规范。 什么是“203.0.113.0”?应用程序的音调可能会向网络中的该地址发送内容,不是吗?

当我以常规(非多播)方式创建客户端时,我使用类似的东西:

DatagramSocket outputClientSocket = new DatagramSocket();
DatagramPacket outputPacket = new DatagramPacket(new byte[512],512,InetAddress.getByName("94.***.89.***"),9898);
...

其中“94.???.89.???”是我服务器的 public IP 地址,9898 是我服务器的端口,它会监听它。像那样:

DatagramSocket serverInputSocket = new DatagramSocket(9898);
DatagramPacket inputServerPacket = new DatagramPacket(new byte[512],512);
serverInputSocket.recieve(inputServerPacket);

收到东西后我可以与客户建立联系,并为他回答一些东西,比如:

DatagramSocket socketForSpecificClient = new DatagramSocket();
InetAddress realClientAddress = inputServerPacket.getAddress();
int realClientPort = inputServerPacket.getPort();
DatagramPacket packetForSpecificClient = new DatagramPacket(new byte[512],512,realClientAddress,realClientPort);
socketForSpecificClient.send(packetForSpecificClient);

这种方法效果很好,即使客户端没有 public IP。 这对我来说是建立连接的绝对清晰的方式,但我不明白应该使用 MulticastSocket 的目的是什么?

多播在IPv4中通常不能跨网段工作。如果您的应用程序应该在 Internet 上运行(而不是例如仅在您控制的 Intranet 内),则您不能基于多播进行通信。

编辑:以下是有关该主题的更多资源:

IP multicast 上的维基百科:

multicast services are generally not available to the average end-user

其他 Whosebug 问题 'UDP Multicast over the internet?'

In general this is not possible since multicast packages aren't routed.

关于 hardforum.com 的讨论 'Does multicast work over the itnernet(sic)?':

ISPs filter mutlicast you can't join a multicast stream over the internet.

这些只是谷歌搜索 'using multicast over the internet' 时最初的几个结果。

地址范围 203.0.113.0/24 保留供 'documentation and example code' 使用,因此示例中的地址 203.0.113.0 不指向真正的端点。

如果您需要一个真实的 public 多播地址并且通过支持多播的 ISP 连接,您必须从 IANA registry 获得一个。任何人都可以向该 IP 地址发送(可能是伪造的)数据,这是对的,但是单播地址存在完全相同的问题。如果您在单播地址上提供服务,任何人都可以连接到该地址并向其发送数据。

引用书Java Network Programming中的段落来构建答案:

How MutlicastSocket at the user side will know where to connect? (public IP/port of the server)?

What is "203.0.113.0"? It is possibles that tones of applications send something to that address in web, isn't it?

首先,您通常应该使用位于 225.0.0.0 到 238.255.255.255 之间的 IP-Address 创建新的多播组。

当主机想要向多播组发送数据时,它会将数据放入多播数据报中,这些数据报只不过是寻址到多播组的 UDP 数据报。多播数据通过 UDP 发送。

多播地址是一组主机的共享地址,称为多播组。 IPv4 多播地址是 CIDR 组 224.0.0.0/4 中的 IP 地址(即,它们的范围从 224.0.0.0 到 239.255.255.255)。

多播组是一组共享多播地址的 Internet 主机。发送到多播地址的任何数据都会中继到该组的所有成员。多播组的成员资格是开放的;主持人可以随时进入或离开群组。组可以是永久的或临时的。 IANA 负责根据需要分发永久多播地址。


多播将数据从一台主机发送到多台不同的主机,但不是发送给所有人;数据仅发送给通过加入特定多播组表示有兴趣的客户端。在某种程度上,这就像一个 public 会议。人们可以随心所欲地来来去去,当他们对讨论不再感兴趣时就离开。在他们到达之前和离开之后,他们根本不需要处理信息:信息只是无法到达他们。在 Internet 上,这种“public 会议”最好使用多播套接字来实现,该多播套接字将数据的副本发送到靠近已声明对数据感兴趣的各方的位置(或一组位置)。

在最好的情况下,数据只有在到达为感兴趣的客户端提供服务的本地网络时才会被复制:数据仅通过 Internet 一次。更实际的是,多个相同的数据副本遍及 Internet;但是,通过仔细选择流被复制的点,网络上的负载被最小化。好的 新闻是程序员和网络管理员不负责选择数据重复的点,甚至不负责发送多个副本;互联网的路由器处理所有这些。


要接收从远程站点多播的数据,首先使用 MulticastSocket() 构造函数创建一个 MulticastSocket。与其他类型的套接字一样,您需要知道要侦听的端口。此代码片段打开一个在端口 2300 上侦听的 MulticastSocket:

MulticastSocket ms = new MulticastSocket(2300);

接下来,使用 MulticastSocket 的 joinGroup() 方法加入多播组:

InetAddress group = InetAddress.getByName("225.2.2.2");
ms.joinGroup(group);

这向您和服务器之间的路径中的路由器发出信号,开始按照您的方式发送数据,并告诉本地主机它应该将寻址到多播组的 IP 数据包传递给您。 加入多播组后,您将像使用 DatagramSocket 一样接收 UDP 数据。

It is possibles that tones of applications send something to that address in web, isn't it?

如果提供服务的地址已知,即使在单播通信的情况下也会面临同样的问题。