2016-09-27 100 views
0

我想綁定一個Java DatagramChannel來偵聽特定端口和子接口上的UDP流量,但我似乎無法讓它在我的linux主機上工作,並在其中創建了多個虛擬網絡子接口(特別是我想聽的一個)如下所示。如果我將Java應用程序託管在同一網絡Windows PC中(使用不同的IP地址,但是在這種情況下,我只需指定偵聽端口並在Windows上不使用子接口),代碼就好了。使用Java DatagramChannel監聽UDP數據報

這是使用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 

接口是設置如下我的Linux框:

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()); 
         } 

回答

0

您正在綁定到192.168.34.1。您只會收到發送到該接口的數據報。除非你真的知道你在做什麼,你應該綁定到0.0.0.0,這是通過完成的,省略了,InetAddress參數,或者使用null。

您對DatagramSocket做的評語本身就是正確的。

+0

@EJB我嘗試過,但不幸的是它不工作,我有一個FTP服務器也運行在這個虛擬接口,我可以很好地登錄,所以IP地址是活着的。我遇到的唯一問題是由於它是一個子接口。我甚至嘗試通過子接口枚舉,並從特定的子接口獲得InetAddress,並使用它無濟於事。 – johnco3