基本信息
源码名称:基于ToyVpn的使用开发
源码大小:31.74M
文件格式:.zip
开发语言:Java
更新时间:2018-07-19
   友情提示:(无需注册或充值,赞助后即可获取资源下载链接)

     嘿,亲!知识可是无价之宝呢,但咱这精心整理的资料也耗费了不少心血呀。小小地破费一下,绝对物超所值哦!如有下载和支付问题,请联系我们QQ(微信同号):813200300

本次赞助数额为: 2 元 
   源码介绍

基于Android官方例子ToyVpn进行的VPN开发

VPN开发,sdk25版本,ndk15版本,vpn开发太难找了做参考吧,用官方给的文件自己搭建的VPN服务器,服务器是我领的免费阿里云,2018/7/31到期






package com.example.pc.service;

import android.app.PendingIntent;
import android.app.Service;
import android.content.Intent;
import android.net.VpnService;
import android.os.Handler;
import android.os.Message;
import android.os.ParcelFileDescriptor;
import android.util.Log;
import android.widget.Toast;

import com.example.pc.Activity.R;

import java.io.FileInputStream;
import java.io.FileOutputStream;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.DatagramChannel;

public class ToyVpnService extends VpnService implements Handler.Callback, Runnable {
    private static final String TAG = "ToyVpnService";

    private String mServerAddress;
    private String mServerPort;
    private byte[] mSharedSecret;
    private PendingIntent mConfigureIntent;

    private Handler mHandler;
    private Thread mThread;

    private ParcelFileDescriptor mInterface;
    private String mParameters;

    @Override
    public int onStartCommand(Intent intent, int flags, int startId) {
        if (mHandler == null) {
            mHandler = new Handler(this);
        }

        if (mThread != null) {
            mThread.interrupt();
        }

        String prefix = getPackageName();
        mServerAddress = intent.getStringExtra(prefix ".ADDRESS");
        mServerPort = intent.getStringExtra(prefix ".PORT");
        mSharedSecret = intent.getStringExtra(prefix ".SECRET").getBytes();


        mThread = new Thread(this, "ToyVpnThread");
        mThread.start();
        return START_STICKY;
    }

    @Override
    public void onDestroy() {
        if (mThread != null) {
            mThread.interrupt();
        }
    }

    @Override
    public boolean handleMessage(Message message) {
        if (message != null) {
            Toast.makeText(this, message.what, Toast.LENGTH_SHORT).show();
        }
        return true;
    }

    @Override
    public synchronized void run() {
        try {
            Log.i(TAG, "Starting");


            InetSocketAddress server = new InetSocketAddress(
                    mServerAddress, Integer.parseInt(mServerPort));


            for (int attempt = 0; attempt < 10; attempt) {
                mHandler.sendEmptyMessage(R.string.connecting);


                if (run(server)) {
                    attempt = 0;
                }

                Thread.sleep(3000);
            }
            Log.i(TAG, "Giving up");
        } catch (Exception e) {
            Log.e(TAG, "Got " e.toString());
        } finally {
            try {
                mInterface.close();
            } catch (Exception e) {

            }
            mInterface = null;
            mParameters = null;

            mHandler.sendEmptyMessage(R.string.disconnected);
            Log.i(TAG, "Exiting");
        }
    }

    private boolean run(InetSocketAddress server) throws Exception {
        DatagramChannel tunnel = null;
        boolean connected = false;
        try {
            tunnel = DatagramChannel.open();

            if (!protect(tunnel.socket())) {
                throw new IllegalStateException("Cannot protect the tunnel");
            }

            tunnel.connect(server);

            tunnel.configureBlocking(false);

            handshake(tunnel);

            connected = true;
            mHandler.sendEmptyMessage(R.string.connected);

            FileInputStream in = new FileInputStream(mInterface.getFileDescriptor());

            FileOutputStream out = new FileOutputStream(mInterface.getFileDescriptor());

            ByteBuffer packet = ByteBuffer.allocate(32767);

            int timer = 0;

            while (true) {
                boolean idle = true;

                int length = in.read(packet.array());
                if (length > 0) {
                    packet.limit(length);
                    tunnel.write(packet);
                    packet.clear();

                    idle = false;

                    if (timer < 1) {
                        timer = 1;
                    }
                }

                length = tunnel.read(packet);
                if (length > 0) {
                    if (packet.get(0) != 0) {
                        out.write(packet.array(), 0, length);
                    }
                    packet.clear();

                    idle = false;

                    if (timer > 0) {
                        timer = 0;
                    }
                }

                if (idle) {
                    Thread.sleep(100);

                    timer = (timer > 0) ? 100 : -100;

                    if (timer < -15000) {
                        packet.put((byte) 0).limit(1);
                        for (int i = 0; i < 3; i) {
                            packet.position(0);
                            tunnel.write(packet);
                        }
                        packet.clear();

                        timer = 1;
                    }

                    if (timer > 20000) {
                        throw new IllegalStateException("Timed out");
                    }
                }
            }
        } catch (InterruptedException e) {
            throw e;
        } catch (Exception e) {
            Log.e(TAG, "Got " e.toString());
        } finally {
            try {
                tunnel.close();
            } catch (Exception e) {
                // ignore
            }
        }
        return connected;
    }

    private void handshake(DatagramChannel tunnel) throws Exception {
        ByteBuffer packet = ByteBuffer.allocate(1024);

        packet.put((byte) 0).put(mSharedSecret).flip();

        for (int i = 0; i < 3; i) {
            packet.position(0);
            tunnel.write(packet);
        }
        packet.clear();

        for (int i = 0; i < 50; i) {
            Thread.sleep(100);

            int length = tunnel.read(packet);
            if (length > 0 && packet.get(0) == 0) {
                configure(new String(packet.array(), 1, length - 1).trim());
                return;
            }
        }
        throw new IllegalStateException("Timed out");
    }

    private void configure(String parameters) throws Exception {
        // If the old interface has exactly the same parameters, use it!
        if (mInterface != null && parameters.equals(mParameters)) {
            Log.i(TAG, "Using the previous interface");
            return;
        }

        Builder builder = new Builder();
        for (String parameter : parameters.split(" ")) {
            String[] fields = parameter.split(",");
            try {
                switch (fields[0].charAt(0)) {
                    case 'm':
                        builder.setMtu(Short.parseShort(fields[1]));
                        break;
                    case 'a':
                        builder.addAddress(fields[1], Integer.parseInt(fields[2]));
                        break;
                    case 'r':
                        builder.addRoute(fields[1], Integer.parseInt(fields[2]));
                        break;
                    case 'd':
                        builder.addDnsServer(fields[1]);
                        break;
                    case 's':
                        builder.addSearchDomain(fields[1]);
                        break;
                }
            } catch (Exception e) {
                throw new IllegalArgumentException("Bad parameter: " parameter);
            }
        }

        try {
            mInterface.close();
        } catch (Exception e) {
            // ignore
        }

        mInterface = builder.setSession(mServerAddress)
                .setConfigureIntent(mConfigureIntent)
                .establish();
        mParameters = parameters;
        Log.i(TAG, "New interface: " parameters);
    }
}