2014-01-11 133 views
1

我的應用程序中有一個組件通過TCP監聽服務器(因此它只接收數據,輸出流從不使用)。可能斷開的唯一原因是技術問題。從邏輯的角度來看,連接應該永遠保持開放。使用Java中的套接字自動重新連接到服務器

我知道如果要檢測連接失敗立即我必須實施某種ping/pong策略。但就我而言,只要完全檢測到丟失的連接(比如說幾分鐘或幾小時後),就沒有必要立即檢測掉連接。

我的問題:

  1. 如果我不使用某種乒乓球/活着檢查策略和連接斷開,我會在一段時間後,我的應用程序邏輯得到一個IOException(它會好起來的如果花費了幾個小時),或者有可能根本沒有檢測到丟棄的連接?
  2. 下面的代碼是否符合我的要求?這有點難看(很多try-catch/while(true)甚至是sleep,但是我想知道是否超時連接可以在一段時間後被識別(例如,由於阻塞BufferedReader.readLine方法中的IOException )
  3. 從上面的問題
  4. 除此之外,有什麼事情我做的更好?

    public class Receiver implements Runnable { 
    
    private Socket socket; 
    private final String host; 
    private final int port; 
    private final int connectionRetryAfter = 10* 1000; 
    
    public Receiver(String host, int port) { // assignments... } 
    
    @Override 
    public void run() { 
        tryCreateSocket(); 
        listenToServer(); 
    } 
    
    private void listenToServer() { 
        String receivedLine; 
        BufferedReader buf; 
        while(true) { 
         try { 
          buf = new BufferedReader(new InputStreamReader(socket.getInputStream())); 
          while ((receivedLine = buf.readLine()) != null) { 
           // do something with 'inputLine' 
          } 
         } catch (IOException e) { 
          // logging 
         } finally { 
          closeSocket(); 
         } 
         // At this point, either an exception occured or the stream equals null (which means it's closed?) 
         tryCreateSocket(); 
        } 
    } 
    
    private void tryCreateSocket() { 
        try { 
         socket = new Socket(host, port); 
        } catch (IOException e) { 
         // logging 
         try { 
          Thread.sleep(connectionRetryAfter); 
         } catch(InterruptedException ex) { 
          // logging 
          Thread.currentThread().interrupt(); 
         } 
         // retry 
         tryCreateSocket(); 
        } 
    } 
    
    private void closeSocket() { 
        if (socket != null) { 
         try { 
          socket.close(); 
         } catch (IOException e) { 
          // logging 
         } 
        } 
    } 
    

    }

回答

1

listenToServer()當然應該拋出,如果連接/重新連接嘗試失敗IOException。考慮這樣的情況當服務器關閉時,做喲你真的想循環這個方法永遠嗎?

+0

謝謝。如果(重新)連接嘗試失敗,肯定會出現IOException。在連接成功建立並且服務器離線後是否會出現IOException的問題。 關於循環:當服務器重新聯機時,我希望應用程序儘快自動重新連接。有沒有更好的方法來實現這個目標?這段代碼在自己的線程中運行,所以其他活動不會同時被阻止。 – alapeno

0

您可能需要避免的一個問題是您tryCreateSocket()進行遞歸調用。如果您的客戶端很長時間斷開連接,則可能會導致內存不足。進一步,當您重新建立連接時,內存堆棧不會被釋放。

我會推薦一個迭代while循環調用tryCreateSocket()來避免這個問題。

相關問題