Сокеты Java на Android, черный экран, когда я пытаюсь подключиться к определенным IP-адресам

#java #android

#java #Android

Вопрос:

Я написал серверно-клиентскую систему на Java (клиент работает как на Windows, так и на Android). Все работает нормально, кроме одного: когда я пытаюсь подключить сокет к IP-адресу, на котором не запущен сервер, моя программа выдает ошибку через AlertDialog на Android, а через a System.out.println("ERROR: bla bla bla..."); и все работает нормально. Но есть некоторые IP-адреса, которые замораживают мои устройства. Появляется черный экран, и через 20/30 секунд приложение перестает отвечать.

Вот мой код:

 public class Client {

   // stuffs

    public void connect() {
        try {
            socketContainer = new CreateSocket(ip, port).execute().get();
            if (socketContainer != null) {
                connected = true;
            }
        } catch (ExecutionException | InterruptedException e) {
            e.printStackTrace();
            connected = false;
        }
    }

   // Other stuffs

    private class SocketContainer {
        private Socket socket;
        private ObjectOutputStream out;
        private ObjectInputStream in;

        public SocketContainer(Socket socket, ObjectInputStream in, ObjectOutputStream out) {
            this.socket = socket;
            this.out = out;
            this.in = in;
        }

        public Socket getSocket() {
            return socket;
        }

        public ObjectOutputStream getOut() {
            return out;
        }

        public ObjectInputStream getIn() {
            return in;
        }
    }

    private class CreateSocket extends AsyncTask<Void, Void, SocketContainer> {

        private String address;
        private int port;

        private CreateSocket(String address, int port) {
            this.address = address;
            this.port = port;
        }

        @Override
        protected SocketContainer doInBackground(Void... voids) {
            try {
                Socket socket = new Socket(address, port);
                socket.connect(new InetSocketAddress(InetAddress.getByName(address), port), 7000);
                ObjectOutputStream out = new ObjectOutputStream(socket.getOutputStream());
                ObjectInputStream in = new ObjectInputStream(socket.getInputStream());
                return new SocketContainer(socket, in, out);
            } catch (UnknownHostException e) {
                e.printStackTrace();
            } catch (IOException e) {
                e.printStackTrace();
            }
            return null;
        }

        @Override
        protected void onPostExecute(SocketContainer sContainer) {
            super.onPostExecute(sContainer);
            synchronized (lock) {
                socketContainer = sContainer;
            }
        }
    }
 

Комментарии:

1. Что такое createSocket? Асинхронная задача. Не используйте .get() на нем!!!

2. Почему? Объект SocketContainer создается с помощью метода .get() createSocket

3. Нет, он создан с new помощью оператора. Избавьтесь от этого .get() .

Ответ №1:

Я сам нашел решение!

Я размещаю решение для тех, у кого такая же проблема:
из developer.android.com:

AsyncTask имеет public final Result get () метод и public final Result get (long timeout, TimeUnit unit) . Я заменил socketContainer = new CreateSocket(ip, port).execute().get(); на socketContainer = new CreateSocket(ip, port).execute().get(5, TimeUnit.SECONDS); . Таким образом, если клиенту не удастся подключиться к серверу через 5 секунд, будет выдана ошибка (в моем случае AlertDialog).

Комментарии:

1. Всегда приятно найти решение самостоятельно. Но… Очень плохое «решение». Избавьтесь от этого .get() и обработайте результат doInBackground в onPostExecute. Вот как вы должны использовать asynctask. Напишите «обычный» код.