@Dmtm
Android

Как правильно открывать неблокирующий сокет из NIO?

переписываю древний проект, используется java.nio
//корутина
            val serverIPAddress = InetAddress.getByName(serverAddressString)
            val serverAddress = InetSocketAddress(serverIPAddress, serverPort)

            val selector = Selector.open()
            val channel = SocketChannel.open()

            channel.configureBlocking(false)
            val channelConnectResult = channel.connect(serverAddress) // тут всегда false
            Timber.d("channel.connect: $channelConnectResult")

            val operations = SelectionKey.OP_CONNECT or SelectionKey.OP_READ or SelectionKey.OP_WRITE
            //selector.wakeup();
            val selectionKey = channel.register(selector, operations)

            var count = 0
            while (!channel.finishConnect() && count<1000) {
                delay(50)
                count++
            }
            if (channel.finishConnect()) {
                Timber.d("channel.finishConnect() IS TRUE, count: $count") //тут  count == 2 или 3
                _connectionState.emit(ConnectionState.Connected())
            } else {
                Timber.e("channel.finishConnect() IS FALSE")
                cancel()
            }

но с сервера ничего не приходит
старый код который работает
public void connect() throws IOException {
        Log.d(TAG, "connect() called, Address: " + serverAddress + ", port: " + serverPort);

        InetAddress serverIPAddress = InetAddress.getByName(serverAddress);
        int port = serverPort;
        InetSocketAddress serverAddress = new InetSocketAddress(serverIPAddress, port);

        SocketChannel channel = SocketChannel.open();
        channel.configureBlocking(false);
        channel.connect(serverAddress);

        selector = Selector.open();
        int operations = SelectionKey.OP_CONNECT | SelectionKey.OP_READ | SelectionKey.OP_WRITE;

        try {
            lock.lock();
            selector.wakeup();
            channel.register(selector, operations);
        } finally {
            lock.unlock();
        }
        socket = channel.socket();

        socketThread = new SocketThread();
        socketThread.start();
    }

private class SocketThread extends Thread {
        @Override
        public void run() {
            Log.d(TAG, "SocketThread run called");
            try {
                Log.d(TAG, "SocketThread run, selector: " + selector);
                Log.d(TAG, "SocketThread run, isInterrupted(): " + currentThread().isInterrupted());
                if (selector != null) {
                    while (!currentThread().isInterrupted()) {
                        if (selector.select(50) > 0) {
                            //Log.d(TAG, "SocketThread selector.select() IS NOT ZERO");
                            boolean doneStatus = processReadySet(selector.selectedKeys());
                            if (doneStatus) {
                                break;
                            }
                        }
                    }
                    Log.d(TAG, "SocketThread run, isInterrupted(): " + currentThread().isInterrupted());
                }
            } catch (DisconnectException e) {
                e.printStackTrace();
            } catch (Exception e) {
                e.printStackTrace();
            } finally {
                try {
                    disconnect();
                } catch (IOException e) {
                    e.printStackTrace();
                } finally {
                    App.getInstance().setSocketClient(null);
                    connectionCallback.onConnectionState(EConnectionState.DISCONNECTED);
                }
            }
        }
    }

public boolean processReadySet(Set readySet) throws Exception {
        //Log.d(TAG, "processReadySet called");
        Iterator iterator = readySet.iterator();
        while (iterator.hasNext()) {
            //Log.d(TAG, "iterator.hasNext(): " + iterator.hasNext());
            SelectionKey key = (SelectionKey) iterator.next();
            iterator.remove();

            //Android's Socket.isConnected() will return true instead of false if the Socket was disconnected incorrectly (i.e. not calling Socket.close).
            //I think the only guaranteed way of knowing if a Socket is still alive is to try to write to it and
            // handle the IOException that it will throw if it is not connected.

            if (key.isConnectable() && !socket.isConnected()) {
                Log.d(TAG, "key.isConnectable()");
                boolean connected = processConnect(key);
                if (!connected) {
                    return true; // Exit
                } else {
                    connectionCallback.onConnectionState(EConnectionState.CONNECTED);
                }
            }
            if (key.isReadable()) {
                Log.d(TAG, "key.isReadable()");
                byte[] data = processRead(key);
                connectionCallback.onIncomingData(data);
            }
            if (key.isWritable()) {
                //Log.d(TAG, "key.isWritable()");
                try {
                    locker.lock();
                    if (dataOut != null) {
                        processWrite(key, dataOut);
                        dataOut = null;
                    }
                } finally {
                    locker.unlock();
                }
            }
        }
        return false; // Not done yet
    }
  • Вопрос задан
  • 98 просмотров
Пригласить эксперта
Ответы на вопрос 1
@Dmtm Автор вопроса
Android
проблема была дальше в корутине
while (isActive) {
                selector.select(50) ///<-----------вот этой строки не было
                val iterator: MutableIterator<SelectionKey> = selectionKey.selector().selectedKeys().iterator()
                while (iterator.hasNext()) {
............
Ответ написан
Комментировать
Ваш ответ на вопрос

Войдите, чтобы написать ответ

Похожие вопросы