@Override
    protected void process() throws IOException {
        int select = mSelector.select();
        if (select == 0) {
            // Wait a short time to let the selector register or interest.
            SystemClock.sleep(SELECTOR_WAIT_TIME);
            return;
        }
        Set<SelectionKey> selectedKeys = mSelector.selectedKeys();
        if (selectedKeys == null) {
            return;
        }
        Iterator<SelectionKey> iterator = selectedKeys.iterator();
        while (iterator.hasNext()) {
            SelectionKey key = iterator.next();
            if (key.isValid()) {
                Object attachment = key.attachment();
                if (attachment instanceof NioCallback) {
                    NioCallback callback = (NioCallback) attachment;
                    try {
                        if (key.isReadable()) {
                            callback.onRead();
                        } else if (key.isWritable()) {
                            callback.onWrite();
                        } else if (key.isConnectable()) {
                            callback.onConnected();
                        }
                    } catch (IOException e) {
                        callback.onClosed();
                        removeTunnel(callback.getTunnel());
                    }
                }
            }
            iterator.remove();
        }
    }
The UDP proxy server is a virtual server, every packet from {@link UdpProxyServerForwarder} is
saw as a connection. It use {@link UdpVATunnel} to bind {@link VirtualGateway} and
{@link NioTunnel} together. Not like TCP, UDP only use {@link UdpRemoteTunnel} to communicate with
real remote server.

@author Megatron King
@since 2018-10-11 17:35
netbare-core/src/main/java/com/github/megatronking/netbare/proxy/UdpProxyServer.java