我正在尝试让多个 Netty 客户端侦听同一个多播组地址。
在同一台计算机上运行这些客户端的问题是每个客户端都绑定到相同的端口(组端口),这会导致端口冲突。
通常可以运行多个客户端来监听同一个地址,那么如何使用 Netty 来实现这一点呢?
这是客户端的代码:
package com.something.tools.udp;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelOption;
import io.netty.channel.FixedRecvByteBufAllocator;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.DatagramChannel;
import io.netty.channel.socket.DatagramPacket;
import io.netty.channel.socket.InternetProtocolFamily;
import io.netty.channel.socket.nio.NioDatagramChannel;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.net.NetworkInterface;
import java.net.SocketException;
public class SimpleMulticastClient {
public static void main(String[] args) throws InterruptedException, SocketException {
String groupAddress = args[0];
int groupPort = Integer.parseInt(args[1]);
String interfaceName = args[2];
Bootstrap b = new Bootstrap();
b.option(ChannelOption.SO_RCVBUF, 1048576);
b.group(new NioEventLoopGroup())
.handler(new SimpleChannelInboundHandler<DatagramPacket>() {
@Override
public void channelRead0(ChannelHandlerContext ctx, DatagramPacket msg) {
System.out.println("Received: " + msg);
}
})
.option(ChannelOption.RCVBUF_ALLOCATOR, new FixedRecvByteBufAllocator(1000))
.option(ChannelOption.SO_REUSEADDR, Boolean.TRUE);
NetworkInterface networkInterface = NetworkInterface.getByName(interfaceName);
DatagramChannel channel = (DatagramChannel)b
.channelFactory(() -> new NioDatagramChannel(InternetProtocolFamily.IPv4))
.localAddress(0)
.bind(groupPort).sync().channel();
System.out.println("UDP client bound to: " + channel.localAddress());
channel.joinGroup(new InetSocketAddress(groupAddress, groupPort), networkInterface).sync();
}
}
如果我运行单个客户端,我可以接收多播流量,OK:
UDP client bound to: /0.0.0.0:19000
Received: DatagramPacket(/192.168.0.4:57335 => /0.0.0.0:19000, PooledUnsafeDirectByteBuf(ridx: 0, widx: 4, cap: 1000))
Received: DatagramPacket(/192.168.0.4:57335 => /0.0.0.0:19000, PooledUnsafeDirectByteBuf(ridx: 0, widx: 4, cap: 1000))
...
如果我尝试在同一台计算机上启动第二个客户端(具有相同的参数),我会收到此异常:
Exception in thread "main" java.net.BindException: Address already in use
我也尝试过改变这一行:
.bind(groupPort).sync().channel();
至:
.bind(0).sync().channel();
并且允许同时运行两个客户端(即没有端口冲突)。然而,客户端随后将停止看到多播流量。
有没有办法让它与 Netty 一起工作?
我在这篇文章中找到了答案:多播绑定 - 地址已在使用中
我需要绑定在多播端口上并使用
SO_REUSEADDR
选项,该选项允许多个客户端绑定在同一地址上。通过这一更改,我能够运行多个客户端并查看多播流量。
我更新了原始帖子中的代码以反映这一点。
我遇到了同样的问题,这个例子很有帮助。谢谢