2017-02-03 1 views
0

В моем приложении я использую подключение сокета TCP для подключения устройства Android к серверу. Socket работает нормально на каждом устройстве, кроме устройств с Android 7+, где я получаю сообщение «Socket is closed». Проблемы с розеткой происходят на Nexus 6P и Samsung s7!TCP-сокет, не работающий на устройствах с Android 7+

Я использую сокет Runnable в службе, инициализирует сокет с:

public class ClientThread implements Runnable { 

    public void run() { 
     while (true) { 
      try { 
       DataHandler.indicator.set(false); 
       mRun = true; 
       if (DataHandler.DOMAIN_IP.contains(":")) { 
        serverAddr = Inet4Address.getByName(DataHandler.DOMAIN_IP.split(":")[0]); 
       } else 
        serverAddr = Inet4Address.getByName(DataHandler.DOMAIN_IP.replace(":3030", "")); 
       Log.i("Socket", "Connecting"); 
       socket = new Socket(serverAddr, SERVERPORT); 
       socket.setKeepAlive(true); 
       socket.setSoLinger(true, 1); 
       socket.setSoTimeout(30000); 
       DataHandler.IP_ADDRESS = socket.getLocalAddress().toString().split("/")[1]; 
       DataInputStream dis = new DataInputStream(socket.getInputStream()); 
       connectionDelay = MIN_WAIT; 
       Log.i("Socket", "Connected"); 
       String serverMessage = ""; 
       byte[] array = new byte[1024]; 
       while (mRun) { 
        int firstbye = dis.read(); 
        int arraylength = dis.available(); 
        array = new byte[arraylength]; 
        dis.read(array, 0, array.length); 
        String str = new String(new byte[]{(byte) firstbye}); 
        serverMessage += str + EncodingUtils.getString(array, "UTF-8"); 
        DataHandler.indicator.set(true); 
        if (firstbye != -1) { 
         String mstString = new String(serverMessage); 
         serverMessage = ""; 
         onReceive(NotificationService.this, mstString); 
        } else { // if (serverMessage.equalsIgnoreCase("")) { 
         try { 
          socket.close(); 
          Log.e("Socket", "Disconnect"); 
          socket = null; 
          stopClient(); 
         } catch (Exception e) { 
          e.getMessage(); 
         } 
         serverMessage = null; 
         DataHandler.indicator.set(false); 
         continue; 

        } 
       } 
      } catch (UnknownHostException e) { 
       isNeedtoWrite = true; 
      } catch (IOException e1) { 
       isNeedtoWrite = true; 
       DataHandler.indicator.set(false); 
      } finally { 
       try { 
        socket.close(); 
        DataHandler.indicator.set(false); 
        Log.e("Socket", "Disconnect"); 
        socket = null; 
        stopClient(); 
       } catch (Exception e) { 
        e.getMessage(); 
       } 
      } 
      try { 
       connectionDelay = Math.min(MAX_WAIT, RandomUtils.nextInt(MIN_WAIT, (int) (connectionDelay * BACKOFF_RATE))); 
       Log.i("SocketSleep", String.valueOf(connectionDelay)); 
       Thread.sleep(connectionDelay); 
       DataHandler.indicator.set(false); 
      } catch (InterruptedException e) { 
       e.getMessage(); 
      } 
     } 
    } 
} 

Перед кодом достигает setSoTimeout он получает исключение.

Я пробовал другое приложение, которое использует ту же логику Socket, и при запуске он работал нормально, а затем он просто неожиданно упал, и он больше не работает. Я проверил на Wireshark, и это происходит:

Wireshark

Кто-нибудь есть какие-либо понятия, что может быть проблема?

+0

Какое исключение вы получаете, может быть networkOnMainThread? –

+0

Я получаю «java.net.SocketException: Socket is closed» на catch (IOException e1) { – Tomek

+0

В android api 24+ они исправили ошибку, которая позволяет использовать OutputStreamWriter в основном потоке, который является сетевой операцией, и его нужно запустить в отдельном потоке, если вы можете сделать что-то подобное. –

ответ

0

Я обнаружил, что проблема была ... Я на самом деле был каким-то код, который под название

socket.getOutputStream().write(GetSendString()); 

вне моего потока, и это вызывает гнездо для отключения/сбоя из-за ошибки NetworkOnMainthread, но я Жду» t правильно обработано Exception!

0

Букс фикс:

Из-за ошибки в предыдущих версиях Android, система не писать флаг в TCP сокет на главном потоке, как нарушение строгого режима. Android 7.0 исправляет эту ошибку. Приложения, демонстрирующие это поведение, теперь вызывают android.os.NetworkOnMainThreadException. Как правило, выполнение сетевых операций в основном потоке является плохой идеей, поскольку эти операции обычно имеют высокую задержку, которая вызывает ANR и jank.

И ссылка на documentation.

+0

Это не проблема. Я запускаю Runnable с «новой Thread (новый ClientThread()), поэтому он использует другой поток, и я попытался поместить код в AsyncTask inBackground, и результат будет таким же – Tomek

+0

Я вижу, что вы используете DateHandler, t konw точно для того, что это или что-то еще, но, может быть, ваш обработчик использует Looper.getMainLooper(), которые используют основной поток? Я просто догадываюсь. –

+0

DataHandler только для статических переменных в этом случае public static AtomicBoolean indicator = new AtomicBoolean (false); – Tomek

-1

Может быть, проблема вызвана чтением InputStream с помощью .read команды. Попробуйте использовать BufferedReader, и аналогичные для OutputStream:

BufferedReader dis = new BufferedReader(
           new InputStreamReader(socket.getInputStream())); 

PrintWriter os_buffer = new PrintWriter(
           new BufferedWriter(new OutputStreamWriter(socket.getOutputStream())), true); 
Смежные вопросы