【发布时间】:2016-09-27 18:46:38
【问题描述】:
我正在尝试绑定 Java DatagramChannel 以侦听特定端口和子接口上的 UDP 流量,但我似乎无法让它在我创建了多个虚拟网络子接口(特别是我想要的那个)的 linux 主机上工作收听如下所示)。如果我在同一个网络 Windows PC 中托管 java 应用程序,代码就很好(使用不同的 IP 地址,但是在这种情况下,对于绑定调用,我只需要指定侦听端口,并且在不使用子接口的 Windows 上)。
这是我的 linux 机器上 ifconfig 的相关部分输出,显示了虚拟网络适配器(子接口)
p2p1:37: flags=4163<UP,BnetROADCAST,RUNNING,MULTICAST> mtu 1500
inet 192.168.34.1 netmask 255.255.0.0 broadcast 192.168.255.255
ether 00:13:72:a5:9c:e2 txqueuelen 1000 (Ethernet)
device interrupt 16
界面设置如下:
ifconfig p2p1:37 192.168.34.1 netmask 255.255.0.0
我用来初始化非阻塞 DatagramChannel 的代码如下所示:(我需要一个DatagramChannel,因为我需要使用选择器以非阻塞方式同时从多个端口读取)。我尝试使用通过channel.socket().bind(new InetSocketAddress(entry.getValue()) 存储在entry.getValue() 中的端口号仅绑定到默认适配器,但没有收到任何数据包。我在某处读到,在构造 DatagramChannel 之后,它默认构造一个绑定到“0.0.0.0”的数据报套接字,一旦绑定它就不能解除绑定——但我不确定。任何指导将不胜感激。
@Override
protected Task<Void> createTask() {
return new Task<Void>() {
@Override
protected Void call() throws Exception {
updateMessage("Running...");
Map<String, DatagramChannel> dlmuChannelInfo = new HashMap<>();
Map<String, DatagramChannel> wsuChannelInfo = new HashMap<>();
try {
// array of bytes for receiving datagrams
ByteBuffer rxBuffer = ByteBuffer.allocateDirect(MAX_PACKET_SIZE);
for (Map.Entry<String, Integer> entry : mDLMUPortInfo.entrySet()) {
DatagramChannel channel = DatagramChannel.open();
// select only works with nonblocking channels
channel.configureBlocking(false);
// NetworkInterface iface = NetworkInterface.getByInetAddress(
// InetAddress.getByName("192.168.34.1"));
// List<NetworkInterface> list = Collections.list(
// NetworkInterface.getNetworkInterfaces());
// for (NetworkInterface next : list) {
// }
channel.socket().bind(new InetSocketAddress(
InetAddress.getByName("192.168.34.1"), entry.getValue()));
dlmuChannelInfo.put(entry.getKey(), channel);
}
// register for reads
try (
// instantiate a selector - note that this autocloses
Selector selector = Selector.open()) {
// register a selector for reads for both the DLMU & WSU
Map<SelectionKey, String> keyServiceInfo = new HashMap<>();
for (Map.Entry<String, DatagramChannel> entry : dlmuChannelInfo.entrySet()) {
SelectionKey key = entry.getValue().register(
selector, SelectionKey.OP_READ);
keyServiceInfo.put(key, entry.getKey());
}
【问题讨论】: