Как избежать, чтобы определенный порт был назначен ServerSocket.accept () - PullRequest
0 голосов
/ 22 мая 2019

В настоящее время я пишу приложение, которое может запускать различные мини-игры, такие как Snake, Tic Tac Toe и т. Д. На интерактивном светодиодном столе.Приложение работает на Raspi без дисплея и получает данные о взаимодействии пользователя с самостоятельно написанным приложением для Android, которое связывается с Pi с помощью TCP Socket s.

, поскольку Sockets самине знаю, где еще подключена другая сторона связи. Теперь я хочу реализовать собственную логику keep-alive, которая заставляет сервер завершать работу клиентского потока после трехкратного ожидания сообщения подтверждения активности в течение 200 мс каждый раз.в случае неожиданного сбоя клиента.

У меня уже есть работающая обычная функция подключения / отключения, которая отключает поток, когда клиент отключается, выходя из приложения.Однако, так как мне нужно, чтобы за светодиодным столом одновременно управлял только один человек (чтобы другие не могли просто подключиться к телефону и закрыть игру во время игры), я хочу быть на 100% уверенным, что если соединение неожиданно оборветсяон будет обнаружен в течение короткого периода времени (около 600 - 5000 мс).

В настоящее время для логики поддержания активности я использую этот код на стороне сервера (создаваемый соответствующим клиентским потоком):

public class KeepAlive implements Runnable {

    private ClientThread endPoint;
    private InputStream in;
    private OutputStream out;

    public KeepAlive(Socket keepAliveSocket, ClientThread endPoint) {

        try {
            in = keepAliveSocket.getInputStream();
            out = keepAliveSocket.getOutputStream();
        } catch (IOException e) {
        }
        this.endPoint = endPoint;
    }

    @Override
    public void run() {

        boolean waitingForResponse = true;
        int keepAlive_waitCycles = 3;
        int keepAlive_waitedCycles = 0;

        while (endPoint.isConnected()) {
            sleep();

            try {
                out.write(1);
                System.out.println("sending");
            } catch (IOException e) {
            }

            sleep();

            try {
                while (waitingForResponse && keepAlive_waitedCycles < keepAlive_waitCycles) {
                    if (in.available() > 0) {
                        in.read();
                        waitingForResponse = false;
                    } else {
                        keepAlive_waitedCycles++;
                        sleep();
                    }
                    System.out.println("receiving - cycle: " + keepAlive_waitedCycles);
                }

                if (waitingForResponse && keepAlive_waitedCycles == 3) {
                    endPoint.setConnection(false);
                } else {
                    keepAlive_waitedCycles = 0;
                }
            } catch (IOException e) {
            }

        }
    }

    private void sleep() {
        int keepAlive_timeout = 3000;

        try {
            Thread.sleep(keepAlive_timeout);
        } catch (InterruptedException e) {
        }
    }

}

И этот код на стороне клиента:

public class KeepAlive implements Runnable{

    private InputStream in;
    private OutputStream out;

    KeepAlive(String serverIP) {
        int keepAlivePort = 42000;
        Log.d("KeepAlive-Test", "KeepAlive created");
        try {
            Socket keepAliveSocket = new Socket(serverIP, keepAlivePort);
            out = keepAliveSocket.getOutputStream();
            in = keepAliveSocket.getInputStream();
        } catch (IOException e) {}
    }

    @Override
    public void run() {
        boolean waitingForResponse = true;
        int keepAlive_waitCycles = 3;
        int keepAlive_waitedCycles = 0;

        Log.d("KeepAlive-Test", "KeepAlive running");

        while(NetworkController.isConnected()) {
            Log.d("KeepAlive-Test", "while-loop");
            sleep();
            try {
                while (waitingForResponse && keepAlive_waitedCycles < keepAlive_waitCycles) {
                    if (in.available() > 0) {
                        in.read();
                        waitingForResponse = false;
                    } else {
                        keepAlive_waitedCycles++;
                        sleep();
                    }

                    Log.d("KeepAlive-Test", "receiving - cycle: " + keepAlive_waitedCycles);
                }

                if (waitingForResponse && keepAlive_waitedCycles == 3) {
                    NetworkController.setConnection(false);
                } else {
                    keepAlive_waitedCycles = 0;
                }

            } catch (IOException e) {}

            if (NetworkController.isConnected()) {
                sleep();

                try {
                    out.write(1);
                    Log.d("KeepAlive-Test", "sending");
                } catch (IOException e) {}
            }
        }
    }

    private void sleep() {
        int keepAlive_timeout = 3000;

        try {
            Thread.sleep(keepAlive_timeout);
        } catch (InterruptedException e) {}
    }
}

Проблема этого подхода заключается в том, что мне кажется, что я не могу получить какие-либо данные на стороне клиента, что, вероятно,вызвано использованием сокета на сервере, который предназначен для регулярного взаимодействия с клиентом (передается в качестве параметра в конструкторе).

После неудачной попытки я попытался использовать DatagramSocket, я действительно не понялкак правильно их использовать для этого.Сейчас я думаю об использовании ServerSocket, однако боюсь, что порт, который я хочу назначить для ServerSocket, может быть заблокирован, например, сокетом для клиентского потока при подключении клиента.

Подводя итог: есть ли способ исключить порт от назначения ServerSocket.accept ()?Таким образом, я мог легко заблокировать этот порт для последующего использования моего ServerSocket в потоке keep-alive.

...