Сокеты для Android и Java. Несколько раз предпринимались попытки подключения сокетов, прежде чем они были успешными

Я пытаюсь войти в IoT и хочу, чтобы приложение отправляло строку с телефона Android на компьютер с Linux. Приложение делает это путем реализации асинтаксической задачи:

//From the java docs, slightly modified
private Void sendThroughSocket(String s, String host, int port) {
    Log.d("E", "In send through  socket");
    final String hostName = host;//Host is the address of the receiver, can be IP or domain
    int portNumber = port;
    //Check if device is connected to internet

    try {
        Socket clientsocket = new Socket(hostName, portNumber); //one of 2-way point communication
        Log.d("E", "Created Socket: ");
        DataOutputStream DOS = new DataOutputStream(clientsocket.getOutputStream());
        if (clientsocket.isConnected())
            Log.d("E", "Socket connected");
        DOS.writeUTF(s);
        clientsocket.close();
    } catch (UnknownHostException e) {
        System.err.println("Don't know about host " + hostName);
        new Runnable() {
            public void run() {
                Toast.makeText(context, "Don't know about host " + hostName, Toast.LENGTH_SHORT).show();
            }
        };

    } catch (IOException e) {
        System.err.println("Couldn't get I/O for the connection to " + hostName);
        //Toast can not be run using asynctask since it acesses UI
        new Runnable() {
            public void run() {
                Toast.makeText(context, "Couldn't get I/O for the connection to " + hostName + " , check the port", Toast.LENGTH_SHORT).show();
            }
        };

    } catch (Exception e) {
        Log.d("E", "#fares" + e.getClass().getName().toString());

    }
    return null;
}

В трех случаях я пытаюсь отправить строку, все запускается с моей панели поиска (я отправляю значение прогресса панели поиска в виде строки): public void onProgressChanged (SeekBar seekBar, int i, boolean b) public void onStartTrackingTouch (SeekBar seekBar) public void onStopTrackingTouch (SeekBar seekBar)

Реализация для всех 3 одинакова: public void onProgressChanged (SeekBar seekBar, int i, boolean b) {

                    progressvalue = i;
                    textView.setText("Brightness = " + progressvalue + " %");


                    if (((RecieverPort.equals("Please enter port Number")) || (RecieverIP.equals("Please enter receiver IP")))) {

                        //Make sure toast isn't persistent
                        if (IPPortToastcount++ == 0)
                            Toast.makeText(MainActivity.this, "Please set both IP and Port ", Toast.LENGTH_SHORT).show();

                    } else {
                        //Check if connected to internet
                        if (!isConnectedtoInternet(MainActivity.this)) {
                            if (ConnectivityToastCount++ < 1)
                                Toast.makeText(MainActivity.this, "You are not connected to the Internet", Toast.LENGTH_SHORT).show();
                        } else {
                            //Send text over wifi
                            SendText ST = new SendText(getApplicationContext());
                            ST.execute(String.valueOf(progressvalue), RecieverIP, RecieverPort);
                            ST.cancel(false);


                        }

                    }


                }

В основном

//Send text over wifi
                            SendText ST = new SendText(getApplicationContext());
                            ST.execute(String.valueOf(progressvalue), RecieverIP, RecieverPort);
                            ST.cancel(false);

На стороне сервера (мой компьютер) все довольно просто:

int portNumber =  44339; // Choose unused port on router
    //Open a socket

    try {

        //System.out.println("in try statement");
        try (ServerSocket serverSocket1 = new ServerSocket(portNumber)) { 
            portNumber = serverSocket1.getLocalPort();
           System.out.println("Created socket at port " + portNumber);
            Socket clientSocket = serverSocket1.accept();

            System.out.println("Accepted");

            DataInputStream DIS = new DataInputStream(clientSocket.getInputStream()); //get input from socket
            //System.out.println("Created reader");

            String inputLine;


           // System.out.println("About to read");


            while (DIS.available() > 0) {
                inputLine = DIS.readUTF();
                System.out.println(inputLine);
            }


        }
    } catch (Exception e) {
        System.out.println("Exception caught when trying to listen on port "
                + portNumber + " or listening for a connection");
        System.out.println(e.getClass().getSimpleName());
    }

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

//Send text over wifi
                            SendText ST = new SendText(getApplicationContext());
                            ST.execute(String.valueOf(progressvalue), RecieverIP, RecieverPort);
                            ST.cancel(false);

необходимы, прежде чем удастся создать сокет и подключиться к компьютеру. Как я могу убедиться, что одного нажатия или одного вызова функции будет достаточно для отправки строки? Извините за длинный пост, но спрашиваю впервые :)

Изменить: мой новый код сервера:

try {

        //System.out.println("in try statement");
        try ( ServerSocket serverSocket1 = new ServerSocket(portNumber)) 
        { 
            portNumber = serverSocket1.getLocalPort();
           System.out.println("Created socket at port " + portNumber);
           while(true){
            Socket clientSocket = serverSocket1.accept();

           // System.out.println("Accepted");

            DataInputStream DIS = new DataInputStream(clientSocket.getInputStream()); //get input from socket
            //System.out.println("Created reader");

            //String inputLine;


           //System.out.println("About to read");
           System.out.println(DIS.readUTF());


            }


        }
    } catch (Exception e) {
        System.out.println("Exception caught when trying to listen on port "
                + portNumber + " or listening for a connection");
        System.out.println(e.getClass().getSimpleName());
    }

Стоит отметить, что даже в цикле while true сервер всегда будет отображать 4 числа, а затем остановится.

Изменить: вот пример журнала: 10-06 20: 08: 09.145 26372-26372 / com.example.fares.ledslider D / E: #fares в значении метода тестирования = 50 10-06 20: 08: 26.475 26372-26372 /com.example.fares.ledslider D / E: #Fares в стартовом отслеживании 10-06 20: 08: 26.722 26372-27004 / com.example.fares.ledslider D / E: #fares Socket connected 10-06 20:08 : 26.810 26372-26764 / com.example.fares.ledslider D / E: #fares Socket connected 10-06 20: 08: 27.241 26372-27003 / com.example.fares.ledslider D / E: #fares Socket connected 10- 06 20: 08: 27.304 26372-26372 / com.example.fares.ledslider D / E: #fares в остановке отслеживания


person Fares Ghazy    schedule 04.10.2017    source источник
comment
Таким образом, ваш сервер закрывается после подключения одного клиента. Дальнейшие клиенты не могут подключиться. Вы должны сделать цикл для сервера, чтобы он ждал следующего клиента, когда он будет готов.   -  person greenapps    schedule 04.10.2017
comment
Цикл должен начинаться с Socket clientSocket = serverSocket1.accept ();   -  person greenapps    schedule 04.10.2017
comment
Просто используйте кнопку, чтобы запустить одну асинтаксическую задачу. Затем посмотрите, сколько времени займет подключение.   -  person greenapps    schedule 04.10.2017
comment
Есть идеи, сколько асинтаксических задач вы запускаете, когда пользователь перемещает ползунок?   -  person greenapps    schedule 04.10.2017
comment
@greenapps Я отвечу по пунктам, и спасибо за вашу помощь :) - Я добавил цикл, он работает лучше, но все еще не быстро - Если я нажимаю где-нибудь на панели поиска, это так же хорошо, как нажатие кнопки, это не так ' т подключиться. -Количество асинктаков является переменным, оно зависит от изменения значения прогресса панели поиска, т.е. если оно идет от 100 до 99, то это 3. Итого формула NumberOfAsyncTasksLaunched = ChangeInSeekBarProgress + 2   -  person Fares Ghazy    schedule 04.10.2017
comment
@greenapps проблема в том, что, хотя приложение отправляет все значения, сервер получает (или, по крайней мере, так кажется) некоторые   -  person Fares Ghazy    schedule 04.10.2017
comment
Клиент всегда должен подключаться. А если нет, то будет исключение. Так что используйте кнопку, чтобы запустить его. Смешно запускать сотню задач, если одна из них уже не работает.   -  person greenapps    schedule 04.10.2017
comment
Добавьте e.printStackTrace (); к каждому блоку улова.   -  person greenapps    schedule 05.10.2017
comment
Вы также не сообщаете, что записано и какие тосты вы видите.   -  person greenapps    schedule 05.10.2017
comment
Вы также должны войти / тост e.getMessage ().   -  person greenapps    schedule 05.10.2017
comment
Я сделал все, что вы предложили в моем приложении для Android, результаты не изменились, ошибок не было, никаких исключений не было. Кнопка тестирования не отправляет сообщение. Метод тестовой кнопки: EditText testbox = (EditText) findViewById ((R.id.TestBox)); Строка testval = testbox.getText (). ToString (); Log.d (E, #fares в значении метода тестирования = + testval); SendText ST = новый SendText (getApplicationContext ()); ST.execute (String.valueOf (testval), RecieverIP, RecieverPort); ST.cancel (ложь); Я обновил свой ответ, чтобы показать соответствующий журнал.   -  person Fares Ghazy    schedule 06.10.2017
comment
Поместите код в блок кода. Не в комментариях. Не люблю читать код в комментариях! Ты? Также поместите журнал в блок кода. Теперь это нечитаемо.   -  person greenapps    schedule 06.10.2017
comment
while (DIS.available() > 0). Удалите это. Клиент отправляет только одну строку utf. Таким образом, сервер может просто прочитать один. Более того, если что-то еще не доступно в первый раз, оно никогда не будет прочитано.   -  person greenapps    schedule 06.10.2017
comment
ST.cancel(false);. Удалите это. Почему это заявление?   -  person greenapps    schedule 06.10.2017
comment
Кажется, что ST.cancel (false) удален, решив мою проблему. Я использовал это утверждение, потому что считал необходимым предотвратить отмену моей асинтаксической задачи. Пожалуйста, ответьте, чтобы я принял ваш ответ. Я не могу тебя отблагодарить   -  person Fares Ghazy    schedule 07.10.2017


Ответы (1)


ST.cancel () можно удалить. Также не дожидаться доступности выглядит не очень хорошо.

person greenapps    schedule 07.10.2017