2017-02-03 41 views
0

在我的應用程序中,我使用TCP套接字連接將android設備連接到服務器。套接字在每臺設備上都能正常工作,但Android 7+設備除外,在此處出現「套接字已關閉」錯誤。 Nexus 6P和三星s7發生套接字問題!TCP socket無法在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它得到例外。

我試過不同的應用程序,它使用相同的套接字邏輯,並開始它正常工作,然後它只是意外下降,它不再工作。我檢查了Wireshark的和發生這種情況:

Wireshark

沒有人有任何線索,可能問題是什麼呢?

+0

你找哪家例外,也許networkOnMainThread? –

+0

我得到了「java.net.SocketException:Socket is closed」on catch(IOException e1){ – Tomek

+0

在android api 24+中,他們修復了一個bug,讓您在主線程上使用OutputStreamWriter,這是網絡操作,它應該運行在單獨的線程,如果你可能做這樣的事情。 –

回答

0

我發現了什麼問題......其實我有一些代碼,稱爲

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

我的線程之外,這是造成插座斷開,因爲NetworkOnMainthread錯誤/崩潰,但我沒有」沒有正確處理異常!

0

布克斯修復:

由於舊版Android設備中的錯誤,系統也沒有標誌寫入主線程作爲一個嚴格的模式違反了TCP套接字。 Android 7.0修復了這個錯誤。展現此行爲的應用程序現在會拋出android.os.NetworkOnMainThreadException。一般來說,在主線程上執行網絡操作是一個糟糕的主意,因爲這些操作通常具有很高的延遲,導致ANR和JANK。

並鏈接到documentation

+0

這不是問題。 我正在用「新線程(new ClientThread())」運行Runnable,因此它使用了不同的線程,並且我試圖將代碼放在背景中的AsyncTask中,結果相同 – Tomek

+0

我看到您使用的是DateHandler,不知道它是什麼或什麼,但也許你的處理程序使用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); 
相關問題