2015-10-27 71 views
0

我開發的系統包括:Android Mobile上的套接字服務器和PC上的套接字客戶端。爲了檢查與客戶端的連接,我從服務器每1秒發送一個" "字符。java.net.SocketException:發送失敗:EPIPE(Broken pipe)在發送字符時檢查套接字連接

但有時候,我得到了異常:

java.net.SocketException: sendto failed: EPIPE (Broken pipe)  
    at libcore.io.IoBridge.maybeThrowAfterSendto(IoBridge.java:506)  
    at libcore.io.IoBridge.sendto(IoBridge.java:475)  
    at java.net.PlainSocketImpl.write(PlainSocketImpl.java:507)  
    at java.net.PlainSocketImpl.access$100(PlainSocketImpl.java:46)  
    at java.net.PlainSocketImpl$PlainSocketOutputStream.write(PlainSocketImpl.java:269)  
    at java.io.OutputStream.write(OutputStream.java:82)  
    at com.foxconn.cnsbgit.mobileterminal.MainActivity$ServerThread.run(MainActivity.jaa:527)  
    at java.lang.Thread.run(Thread.java:856)  
Caused by: libcore.io.ErrnoException: sendto failed: EPIPE (Broken pipe)  
    at libcore.io.Posix.sendtoBytes(Native Method)  
    at libcore.io.Posix.sendto(Posix.java:151)  
    at libcore.io.BlockGuardOs.sendto(BlockGuardOs.java:177)  
    at libcore.io.IoBridge.sendto(IoBridge.java:473)  
    ... 6 more 

發送Thread檢查連接如下:

while (true) { 
    if (client != null) { 
     try { 
       client.getOutputStream().write(" ".getBytes()); // Get exception when sending character 
       Thread.sleep(1000); 
       mHandler.post(new Runnable() { 
        @Override 
        public void run() { 
         txtConnectionStatus.setText(R.string.smoConnectOK); 
        } 
       }); 
     } catch (Exception e) { 
       e.printStackTrace(); // Get exception at here 
       mHandler.post(new Runnable() { 
        @Override 
        public void run() { 
         if !txtConnectionStatus.getText().toString().contains("FAIL")) { 
          txtConnectionStatus.setText(R.string.connectionFailString); 
         } 
        } 
       }); 
       try { 
        Thread.sleep(5000); 
       } catch (InterruptedException e1) { 
        e1.printStackTrace(); 
       } 
      } 
    } 
} 

更新時間: 然後,我有輸入和發送數據到客戶端。當心跳和數據同時發送時,連接是否丟失? :

public class SendDataThread implements Runnable { 

    @Override 
    public void run() { 
     try { 
      if (client != null) { 
       sendDataStream = client.getOutputStream(); 
       sendDataStream.write(dataSend); //dataSend is a byte array 
       sendDataStream.flush(); 

       mHandler.post(new Runnable() { 
        @Override 
        public void run() { 
         edtCommand.selectAll(); 
        } 
       }); 
      } 
     } catch (final Exception e) { 
      mHandler.post(new Runnable() { 
       @Override 
       public void run() { 
        txtRec.setText(e.toString()); 
       } 
      }); 
     } 
    } 
} 

回答

0

但有時候,我得到了異常:

java.net.SocketException異常:SENDTO失敗:EPIPE(碎管),如果你寫一個

EPIPE被觸發套接字但對方已關閉套接字。因此這個異常表明你不能再通過這個套接字進行通信。

+0

寫''「'經常可能是連接關閉的原因,兄弟? –

+0

@MrNeo:「」不關閉連接,服務器。由於我不知道你的服務器是什麼,我不能確定是否太多「」會導致它關閉連接。 –

+0

我已更新我的問題以獲取更多信息。當我同時發送心跳和數據時,我的連接是否丟失? –

0

您的系統完全按照設計工作。你發出心跳,失敗,你發現一個死亡的連接。這是代碼的目的。

+0

我已更新我的問題以獲取更多信息。當我同時發送心跳和數據時,我的連接是否丟失? –

+0

@MrNeo號碼當對端關閉他的末端或檢測到網絡故障時,它會丟失。對方的行爲是否正常? – EJP

+0

我發現如果我打開並且什麼也不做,很長時間沒關係。但是,如果我開始發送並獲取第十次數據,將發生異常:( –

2

當Android保持空閒狀態時,設備鎖定,然後進入深度睡眠模式。在Android系統的深度睡眠模式下,關閉現有的網絡連接,如TCP或UDP。如果您的應用連接到服務器,它將失去與服務器的連接,並嘗試基於爲客戶端配置的重新連接嘗試方法重新連接。但是如果您的應用程序是服務器,則所有客戶端都將失去與服務器的連接,並且必須再次在服務器中啓動套接字,並嘗試再次從客戶端進行連接。

由於TCP連接與進入睡眠狀態的計算機不能很好地交互,因此保持TCP連接處於打開狀態可能不適用於移動設備。問題情形是:你的Android用戶在你的應用程序運行時讓他的Android設備進入休眠狀態,然後遠程用戶的程序(或者TCP連接另一端的任何程序)通過TCP流發送一些數據。遠程用戶的程序永遠不會從Android設備收回任何ACK,因爲當然Android設備處於睡眠狀態,所以遠程設備的TCP堆棧假定它發送的TCP數據包必須丟失,並且它通過增加其超時時間來響應,降低其TCP窗口大小(又名TCP-packet-allowed-in-flight-at-once),並重新發送TCP數據包。但Android設備仍然在睡覺,因此同樣的事情再次發生。結果是,幾分鐘後,TCP連接的遠端已經放慢,即使Android設備被喚醒,TCP連接可能會太慢而無法使用 - 在這一點上,您的程序將需要關閉陷入困境的TCP連接並重新啓動一個新連接,那麼爲什麼還要努力使其保持開放?

獲取一個PARTIAL_WAKE_LOCK和陷阱當屏幕熄滅。然後 禁用並重新啓用wifi。這是有效的,因爲只有當屏幕關閉時纔開啓 過濾器,所以在屏幕關閉的情況下啓動wifi將保持其工作狀態,直到屏幕再次關閉。