java - Android - Vpnservice DatagramChannel.open() 不起作用

标签 java android networking vpn packets

我想创建应用程序,它可以重新路由数据包。我使用 vpnservice (因为不需要 root 手机),使用 toyVpn 和此代码 http://www.thegeekstuff.com/2014/06/Android-vpn-service/ 但问题出在这一行 DatagramChanneltunnel = DatagramChannel.open(); 该行抛出异常。 这是我的代码

public class MyVpnService extends VpnService {

    public static String CONNECTION = "StartService";
    public static String DISCONNECTION = "StopService";
    public static boolean work = false;
    private Thread mThread;
    private ParcelFileDescriptor mInterface;
    Builder builder = new Builder();

    // Services interface
    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        // Start a new session by creating a new thread.
        if (intent != null && DISCONNECTION.equals(intent.getAction())) {
            work = false;
            stopForeground(true);
            mThread.interrupt();
            stopSelf();

            return START_NOT_STICKY;
        }
        work = true;
        mThread = new Thread(new Runnable() {
            @Override
            public void run() {
                try {
                    Log.d("VPNservice", "0");
                    mInterface = builder.setSession("MyVPNService")
                            .addAddress("192.168.1.3", 24)
                            .addDnsServer("8.8.8.8")
                            .addRoute("0.0.0.0", 0).establish();
                    FileInputStream in = new FileInputStream(
                            mInterface.getFileDescriptor());
                    FileOutputStream out = new FileOutputStream(
                            mInterface.getFileDescriptor());
                    Log.d("VPNservice", "1 " + (mInterface != null));
                    DatagramChannel tunnel = DatagramChannel.open();
                    Log.d("VPNservice", "2 " + (tunnel != null));
                    Log.d("VPNservice", "3 " + tunnel.connect(new InetSocketAddress("127.0.0.1", 8087)));
                    //tunnel.connect(new InetSocketAddress("127.0.0.1", 8087));
                    tunnel.configureBlocking(false);
                    protect(tunnel.socket());
                    //e. Use a loop to pass packets.
                    ByteBuffer packet = ByteBuffer.allocate(Short.MAX_VALUE);
                    Log.d("VPNservice", "4");
                    while (!Thread.interrupted()) {
                        Log.d("VPNservice", "5");
                        int length = in.read(packet.array());
                        if (length > 0) {
                            packet.limit(length);
                            tunnel.write(packet);
                            // There might be more outgoing packets.
                            Log.d("VPNservice", "6");
                        }
                        Log.d("VPNservice", "7");
                        length = tunnel.read(packet);
                        Log.d("VPNservice", "8");
                        if (length > 0) {
                            if (packet.get(0) != 0) {
                                out.write(packet.array(), 0, length);
                                Log.d("VPNservice", "9");
                            }
                            packet.clear();
                            Log.d("VPNservice", "10");
                        }
                        Thread.sleep(100);
                        Log.d("VPNservice", "11");
                    }

                } catch (Exception e) {
                    e.printStackTrace();
                } finally {
                    try {
                        if (mInterface != null) {
                            mInterface.close();
                            mInterface = null;
                        }
                    } catch (Exception e) {

                    }
                }
            }

        }, "MyVpnRunnable");

        //start the service
        mThread.start();
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        // TODO Auto-generated method stub
        if (mThread != null) {
            mThread.interrupt();
        }
        super.onDestroy();
    }
}

this is log:

 07-02 15:13:09.271 8853-8853/app.my.myvpnservice D/ActivityThread: SVC-Calling onStartCommand: app.my.myvpnservice.MyVpnService@424f59f0, flags=0, startId=1
07-02 15:13:09.272 8853-8853/app.my.myvpnservice D/dalvikvm: create interp thread : stack size=128KB
07-02 15:13:09.272 8853-8853/app.my.myvpnservice D/dalvikvm: create new thread
07-02 15:13:09.274 8853-8853/app.my.myvpnservice D/dalvikvm: new thread created
07-02 15:13:09.274 8853-8853/app.my.myvpnservice D/dalvikvm: update thread list
07-02 15:13:09.274 8853-9304/app.my.myvpnservice D/dalvikvm: threadid=11: interp stack at 0x7d83d000
07-02 15:13:09.274 8853-9304/app.my.myvpnservice D/dalvikvm: threadid=11: created from interp
07-02 15:13:09.274 8853-8853/app.my.myvpnservice D/dalvikvm: start new thread
07-02 15:13:09.274 8853-9304/app.my.myvpnservice D/dalvikvm: threadid=11: notify debugger
07-02 15:13:09.274 8853-9304/app.my.myvpnservice D/dalvikvm: threadid=11 (MyVpnRunnable): calling run()
07-02 15:13:09.275 8853-8853/app.my.myvpnservice D/ActivityThread: SVC-SERVICE_ARGS handled : 0 / ServiceArgsData{token=android.os.BinderProxy@424ef338 startId=1 args=Intent { act=StartService cmp=app.my.myvpnservice/.MyVpnService }}
07-02 15:13:09.275 8853-9304/app.my.myvpnservice D/VPNservice: 0
07-02 15:13:09.306 8853-8853/app.my.myvpnservice D/ActivityThread: SVC-BIND_SERVICE handled : 0 / BindServiceData{token=android.os.BinderProxy@424ef338 intent=Intent { act=android.net.VpnService cmp=app.my.myvpnservice/.MyVpnService }}
07-02 15:13:09.447 8853-9304/app.my.myvpnservice D/VPNservice: 1 true
07-02 15:13:09.471 8853-9304/app.my.myvpnservice W/System.err: java.net.SocketException: socket failed: EACCES (Permission denied)
07-02 15:13:09.481 8853-9304/app.my.myvpnservice W/System.err:     at libcore.io.IoBridge.socket(IoBridge.java:622)
07-02 15:13:09.481 8853-9304/app.my.myvpnservice W/System.err:     at java.nio.DatagramChannelImpl.<init>(DatagramChannelImpl.java:75)
07-02 15:13:09.481 8853-9304/app.my.myvpnservice W/System.err:     at java.nio.SelectorProviderImpl.openDatagramChannel(SelectorProviderImpl.java:33)
07-02 15:13:09.481 8853-9304/app.my.myvpnservice W/System.err:     at java.nio.channels.DatagramChannel.open(DatagramChannel.java:66)
07-02 15:13:09.481 8853-9304/app.my.myvpnservice W/System.err:     at app.my.myvpnservice.MyVpnService$1.run(MyVpnService.java:50)
07-02 15:13:09.482 8853-9304/app.my.myvpnservice W/System.err:     at java.lang.Thread.run(Thread.java:848)
07-02 15:13:09.482 8853-9304/app.my.myvpnservice W/System.err: Caused by: libcore.io.ErrnoException: socket failed: EACCES (Permission denied)
07-02 15:13:09.482 8853-9304/app.my.myvpnservice W/System.err:     at libcore.io.Posix.socket(Native Method)
07-02 15:13:09.482 8853-9304/app.my.myvpnservice W/System.err:     at libcore.io.BlockGuardOs.socket(BlockGuardOs.java:181)
07-02 15:13:09.482 8853-9304/app.my.myvpnservice W/System.err:     at libcore.io.IoBridge.socket(IoBridge.java:607)
07-02 15:13:09.482 8853-9304/app.my.myvpnservice W/System.err: 	... 5 more
07-02 15:13:09.536 8853-9304/app.my.myvpnservice D/dalvikvm: threadid=11: exiting
07-02 15:13:09.536 8853-9304/app.my.myvpnservice D/dalvikvm: threadid=11: bye!
07-02 15:13:09.583 8853-8853/app.my.myvpnservice D/ActivityThread: SVC-UNBIND_SERVICE handled : 0 / BindServiceData{token=android.os.BinderProxy@424ef338 intent=Intent { act=android.net.VpnService cmp=app.my.myvpnservice/.MyVpnService }}

我还有一个问题。我是否必须为此使用 VPN 服务器,或者我可以像不使用此服务一样以默认方式(隧道)返回数据包吗?

最佳答案

这个问题很老了,但是......

你的堆栈跟踪有这一行:

SocketException: socket failed: EACCES (Permission denied)

这似乎是一个权限问题。您可以通过将 INTERNET 权限添加到 AndroidManifest.xml 中来解决此问题(如果您已经拥有此权限但仍然遇到此异常,只需添加ACCESS 权限如下):

<manifest
    ..... >
    <uses-permission android:name="android.permission.INTERNET" />
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
    <uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
    <application
          .... 

关于java - Android - Vpnservice DatagramChannel.open() 不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44871216/

相关文章:

Android pre-lollipop 设备给出错误 "SSL handshake aborted: ssl=0x618d9c18: I/O error during system call, Connection reset by peer"

java - AdMob 横幅未在 Android (Cocos2d-x) 上显示测试广告

android - 如何摆脱gridview中的空格

android - iOS/Android - 你能读/写移动操作系统上的数据链路层吗?

java - 有什么办法可以让这个更加紧凑吗?

java - HQL如何连接三张表

java - Spring Hibernate 获取选中的列

java - java "platform agnosticism"是否有可能失败的情况?

android - 我应该为 GPS 和网络提供商使用单独的 locationManager 吗?

c++ - winsock 连接持续多长时间?