2015-03-13 27 views
4

我可以将套接字绑定到android 5.x中的特定网络。 如何绑定DatagramSocket?可能吗? 寻找来源,如果它可以用没有运气的反射来完成。 https://developer.android.com/reference/android/net/Network.html#bindSocket(java.net.Socket)Android棒棒糖将套接字绑定到特定网络。 DatagramSocket怎么样?

UPDATE ParcelFileDescriptor.fromDatagramSocket(socket).getFd()可以替换辅助函数getFileDescriptor。也有结合直接向中FileDescriptor的API 23 https://developer.android.com/reference/android/net/Network.html#bindSocket%28java.io.FileDescriptor%29

更新新功能:刚才看到在API层面一些灰色额外的新功能22 https://developer.android.com/reference/android/net/Network.html#bindSocket(java.net.DatagramSocket)

UPDATE:也可以用反射完成API等级21

private static int getFileDescriptor(DatagramSocket socket) throws SocketException { 
 
     try { 
 
      Field implField = DatagramSocket.class.getDeclaredField("impl"); 
 
      implField.setAccessible(true); 
 
      
 
      DatagramSocketImpl implValue = (DatagramSocketImpl)implField.get(socket); 
 
      Field fdField = DatagramSocketImpl.class.getDeclaredField("fd"); 
 
      fdField.setAccessible(true); 
 
      
 
      FileDescriptor fdValue = (FileDescriptor)fdField.get(implValue); 
 
      Field descField = FileDescriptor.class.getDeclaredField("descriptor"); 
 
      descField.setAccessible(true); 
 
      
 
      return (Integer)descField.get(fdValue); 
 
      
 
     } catch (NoSuchFieldException e) { 
 
      e.printStackTrace(); 
 
      throw new AssertionError(e); 
 
     } catch (IllegalAccessException e) { 
 
      e.printStackTrace(); 
 
      throw new AssertionError(e); 
 
     } 
 
    } 
 

 
private DatagramChannel createDatagramChannel(Network activeWifiNetwork) throws IOException{ 
 
     DatagramChannel channel = DatagramChannel.open(); 
 
     try{ 
 
      if (activeWifiNetwork == null) { 
 
       Log.d(TAG, "No active network to bind to "); 
 
       return channel; 
 
      } 
 
      Class<?> networkUtils = Class.forName("android.net.NetworkUtils"); 
 
      for (Method m : networkUtils.getDeclaredMethods()) { 
 
       if (m.getName().equalsIgnoreCase("bindSocketToNetwork")){ 
 
        DatagramSocket socket = channel.socket(); 
 
        socket.getReuseAddress(); 
 
        int socketFileDescriptor = getFileDescriptor(socket); 
 
        int result = (Integer) m.invoke(null, socketFileDescriptor , Integer.valueOf(activeWifiNetwork.toString())); 
 
        Log.d(TAG, "Result bind datagram to network is " + result); 
 
        if (result != 0){ 
 
         throw new Exception("Error binding socket to network"); 
 
        } 
 
        break; 
 
       } 
 
      } 
 
     } catch(Exception ex){ 
 
      ex.printStackTrace(); 
 
     } 
 
     return channel; 
 
    }

+0

您是否尝试用'ParcelFileDescriptor.fromDatagramSocket(socket).getFd()'替换getFileDescriptor()? – surlac 2016-02-18 02:22:55

+0

你说得对。它可以被替换。谢谢。还发现这个存在于23 https://developer.android.com/reference/android/net/Network.html#bindSocket%28java.io.FileDescriptor%29 – 2016-02-19 06:09:32

+0

正确。但是您的createDatagramChannel()仍然需要绑定DatagramSocket到API 21上的网络,因为'bindSocket(DatagramSocket套接字)'在API 22上可用。 – surlac 2016-02-19 18:39:20

回答

-1

你已经能够为DatagramSocket绑定到SPE (至少从1997年开始)。

+0

对于特定的网络[https://developer.android.com/reference/ android/net/Network.html]自2015年以来。 – 2015-03-14 14:34:39

+0

@downvoter你开玩笑。我是在1997年做的。看到Javadoc。 – EJP 2016-11-25 10:02:21