Android Lollipop将套接字绑定到特定网络。那么DatagramSocket呢?

时间:2015-03-13 19:00:44

标签: android sockets networking bind

我可以将socket绑定到android 5.x中的特定网络。 如何绑定DatagramSocket?可能吗? 如果可以通过反射而没有运气来查看来源。 https://developer.android.com/reference/android/net/Network.html#bindSocket(java.net.Socket)

UPDATE ParcelFileDescriptor.fromDatagramSocket(socket).getFd()可以替换辅助函数getFileDescriptor。还有一个新功能,它直接绑定到API 23 https://developer.android.com/reference/android/net/Network.html#bindSocket%28java.io.FileDescriptor%29

中的FileDescriptor

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

更新:也可以使用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 个答案:

没有答案