2012-08-27 101 views
1

我正在使用Apache Commons TelnetClient爲某些交換機創建自動telnet界面。如果我直接從機器telnet到交換機,連接似乎永遠不會超時。隨機地,在Java程序中,連接似乎與InputStream一起立即關閉。我試圖建立一個檢查,看到連接失敗,並嘗試再次進行連接,但如果它第一次失敗,它總是失敗。Java TelnetClient InputStream在打開後關閉

import org.apache.commons.net.telnet.TelnetClient; 

    public String connect() 
    { 
    String errorMessage = null; 
    tcConnectionHandle = new TelnetClient(); 
    tcConnectionHandle.setDefaultTimeout(iTimeOutMilliseconds); 

    try 
    { 
     tcConnectionHandle.connect(strConnectionIP, intConnectionPort); 
     osOutput = tcConnectionHandle.getOutputStream(); 
     isInput = tcConnectionHandle.getInputStream(); 
     int availableBytes = isInput.available(); 

     while(availableBytes <= 0) 
     { 
      tcConnectionHandle = null; 
      isInput = null; 
      osOutput = null; 
      Thread.sleep(500); 
      tcConnectionHandle = new TelnetClient(); 
      Thread.sleep(500); 
      tcConnectionHandle.setDefaultTimeout(iTimeOutMilliseconds); 
      Thread.sleep(500); 
      tcConnectionHandle.connect(strConnectionIP, intConnectionPort); 
      Thread.sleep(500); 
      osOutput = tcConnectionHandle.getOutputStream(); 
      Thread.sleep(500); 
      isInput = tcConnectionHandle.getInputStream(); 
      Thread.sleep(500); 
      availableBytes = isInput.available(); 
      System.out.println("reopened: " + availableBytes); 
     } 
    } 
    catch(InterruptedException iX) 
    { 
     errorMessage = "Could not establish connection. " + iX.getLocalizedMessage(); 
    } 
    catch(SocketException sX) 
    { 
     errorMessage = sX.getMessage(); 
    } 
    catch(IOException ioX) 
    { 
     errorMessage = ioX.getMessage(); 
    } 

    return errorMessage; 
    } 

如果我遺漏了Thread.sleep(500)它永遠不會有任何availableBytes。暫停後,結果爲20,但是,如果我嘗試使用isInput.read(),它將返回-1,這表示InputStream已關閉。

我正在尋找一種方法來捕捉連接失敗並再次嘗試連接。它發生得太頻繁,不能再試一次。

+0

爲什麼要測試可用字節爲負數或零?測試它有什麼意義?誰說必須立即連接數據?只要讀一下。它會阻止,直到數據到達。使用讀取超時來控制它。 – EJP

+0

我正在做測試,因爲讀取失敗並返回-1(如我的代碼塊所述)。直到數據到達,因爲InputStream被關閉,它才被阻塞。 –

回答

1

我認爲連接到TelnetClient的InputStream隨機處於關閉狀態。任何在該狀態下嘗試讀取它的嘗試都會導致通信失敗,即使我以後創建了新的TelnetClient對象並重新連接到同一個Telnet服務器。這沒有道理,但我決定嘗試一種新方法,而不是搞清楚TelnetClient類中發生了什麼。

我使用implements TelnetInputListener來解決這個問題。當調用telnetInputAvailable()時,InputStream偶爾會爲空,但現在我可以通過對該函數的特定調用不做任何事情來恢復它。

public String connect() 
{ 
    String errorMessage = null; 
    tcConnectionHandle = new TelnetClient(); 
    tcConnectionHandle.setDefaultTimeout(iTimeOutMilliseconds); 
    tcConnectionHandle.registerInputListener(this); 

    try 
    { 
     tcConnectionHandle.connect(strConnectionIP, intConnectionPort); 
     osOutput = tcConnectionHandle.getOutputStream(); 
     isInput = tcConnectionHandle.getInputStream(); 
    } 
    catch(SocketException sX) 
    { 
     errorMessage = sX.getMessage(); 
    } 
    catch(IOException ioX) 
    { 
     errorMessage = ioX.getMessage(); 
    } 

    return errorMessage; 
} 

public Matcher waitForRegularExpression(String regularExpression) 
{ 
    Matcher matcher; 
    Pattern pattern = Pattern.compile("(?s)" + regularExpression); 
    StringBuilder warningLog = new StringBuilder(); 

    synchronized(sbInputBuffer) 
    { 
     matcher = pattern.matcher(sbInputBuffer.toString()); 

     while(!matcher.find()) 
     { 
     try 
     { 
      int inputBufferSize = sbInputBuffer.length(); 
      sbInputBuffer.wait(iTimeOutMilliseconds); 

      if(inputBufferSize == sbInputBuffer.length()) 
      { 
       warningLog.append("Did not find pattern and no new input."); 
       logWarning(warningLog.toString()); 
       return null; 
      } 
     } 
     catch(InterruptedException intX) 
     { 
      warningLog.append("Interrupted waiting on input. ").append(intX.getLocalizedMessage()); 
     } 

     matcher = pattern.matcher(sbInputBuffer.toString()); 
     } 

     sbInputBuffer.delete(0, matcher.end()-1); 
    } 

    if(!warningLog.toString().isEmpty()) 
    { 
     logWarning(warningLog.toString()); 
    } 

    return matcher; 
} 

@Override 
public void telnetInputAvailable() 
{ 
    synchronized(sbInputBuffer) 
    { 
     StringBuilder warningLog = new StringBuilder(); 
     int readBytes = -2; 

     if(isInput != null) 
     { 
     try 
     { 
      readBytes = isInput.read(); 

      if(readBytes > 0) 
      { 
       sbInputBuffer.append((char)readBytes); 
      } 

      sbInputBuffer.notify(); 
     } 
     catch(IOException ioX) 
     { 
      warningLog.append("Failed for IO: ").append(ioX.getLocalizedMessage()).append(" - input so far: ") 
       .append(sbInputBuffer.toString()).append("\nRead bytes: ").append(readBytes).append("\n"); 
      logWarning(warningLog.toString()); 
     } 
     } 
    } 
}