2015-02-12 49 views
1

我有我的應用程序通過SSH(使用JSch)連接到服務器,但應用程序不能跟上,如果我發送命令而不等待結果回來和它會在未等待下一個命令發送時錯過應答。線程內服務 - 需要等到線程完成[Android]

我嘗試了一些方法,例如使用Object來同步Thread並使用wait()和notify(),但UI線程保持凍結。和thread.join()工作,但導致它運行速度非常緩慢,因爲它凍結之間的命令。長話短說,我需要等待來自服務器的回覆,處理並繪製它,然後發送下一個命令。

任何幫助非常感謝,因爲這是我的計算項目。 :d

 
 
//A snippet of my service procedure that handles the SSH connections 
 

 
public String sendCommand(final String command) { 
 
     Finished = false; 
 
     final Thread sshServiceThread = new Thread(new Runnable() { 
 
      String sshPassword = null; 
 
      private volatile boolean running = true; 
 

 
       @Override 
 
       public void run() { 
 
        while (running) { 
 
         try { 
 
          session = jSch.getSession(username, host, port); 
 
          checkPassword(); 
 
          session.setPassword(sshPassword); 
 
          session.setConfig("StrictHostKeyChecking", "no"); 
 
          //TODO - REMOVE THIS 
 
          Log.w("DEBUG", "Host: " + host + " Username: " + username + " Password: " + password); 
 
          Log.w("Security", "REMOVE THIS BEFORE RELEASE"); 
 
          session.connect(); 
 
          channel = session.openChannel("shell"); 
 

 
          DataOutputStream dataOut = new DataOutputStream(channel.getOutputStream()); 
 

 
          InputStream in = channel.getInputStream(); 
 

 
          channel.connect(); 
 

 
          //Send command 
 
          Log.w("Command", "Command: " + command); 
 
          dataOut.writeBytes(command + " && echo TheCommandWasFinished" + "\r\n"); 
 
          dataOut.flush(); 
 

 
          byte[] tmp = new byte[1024]; 
 
          String replyLine = ""; 
 
          try { 
 
           while (true) { 
 
            while (in.available() > 0) { 
 
             int i = in.read(tmp, 0, 1024); 
 
             if (i < 0) 
 
              break; 
 
             String lastLine = replyLine; 
 
             replyLine = (new String(tmp, 0, i)); 
 

 
             if (!replyLine.contains("&& echo TheCommandWasFinished")) { 
 
              if (replyLine.contains("TheCommandWasFinished")) { 
 
               String result = lastLine; 
 
               Log.w("Result", result); 
 
               reply = result; 
 
               synchronized (syncObject) { 
 
                notify(); 
 
               } 
 
               return; 
 
              } 
 
             } 
 
            } 
 
           } 
 
          } catch (Exception exception) { 
 
           Log.w("Exception", exception); 
 
          } 
 

 
         } catch (JSchException jschX) { 
 
          Log.w("Exception", jschX); 
 

 
          if (jschX.toString().contains("timeout")) { 
 
           Log.w("Error", "IP Address is incorrect"); 
 
           Toast.makeText(getApplicationContext(), "Cannot connect to host, Check IP and connection.", Toast.LENGTH_LONG).show(); 
 

 
          } 
 

 
          if (jschX.toString().contains("Auth fail")) { 
 
           Log.w("Error", "Username/Password Incorrect"); 
 
           Toast.makeText(getApplicationContext(), "Username/Password Incorrect", Toast.LENGTH_LONG).show(); 
 
          } 
 

 
          if (jschX.toString().contains("ECONNRESET")) { 
 
           Toast.makeText(getApplicationContext(), "Connection failure", Toast.LENGTH_LONG).show(); 
 
          } 
 

 
         } catch (IOException Exception) { 
 
          Log.w("Exception", Exception); 
 
         } 
 
        } 
 
       } 
 
      void checkPassword() { 
 
       Log.w("Password set", "Password: " + sshService.password); 
 
       sshPassword = sshService.password; 
 
      } 
 
     }); 
 
     sshServiceThread.start(); 
 

 
     try { 
 
      synchronized(syncObject) { 
 
       syncObject.wait(3000); 
 
      } 
 
     } 
 
     catch (Exception Exception) { 
 
      Log.w("Exception", Exception); 
 
     } 
 
     Finished = true; 
 
     return reply; 
 
    }

// Last few lines of my Logcat 
 

 
02-12 00:11:10.281 32701-32701/com.lonedev.slypanel W/Values﹕ Host: 192.168.0.14 Username: adam 
 
02-12 00:11:10.282 32701-32701/com.lonedev.slypanel W/Save﹕ Saved 192.168.0.14 adam 
 
02-12 00:11:10.354 32701-32701/com.lonedev.slypanel W/Host:﹕ 192.168.0.14 
 
02-12 00:11:10.355 32701-32701/com.lonedev.slypanel W/Host:﹕ 192.168.0.14 
 
02-12 00:11:13.398 32701-684/com.lonedev.slypanel W/Password set﹕ Password: ********** 
 
02-12 00:11:13.399 32701-684/com.lonedev.slypanel W/DEBUG﹕ Host: 192.168.0.14 Username: adam Password: ********** 
 
02-12 00:11:13.399 32701-684/com.lonedev.slypanel W/Security﹕ REMOVE THIS BEFORE RELEASE 
 
02-12 00:11:13.794 32701-684/com.lonedev.slypanel W/Command﹕ Command: top -b -n2 | grep "Cpu(s)" | awk '{print $2 + $4}' | tail -1 
 

 
// This should return a value for cpu usage e.g. 37.5 
 
// UI Freezes here

我已閱讀,我在這裏可以使用的AsyncTask,而不是一個線程...不知道如果我能做到的裏面儘管...服務:P

回答

0

請參閱#sending-commands-to-server-via-jsch-shell-channel

...如果你不知道有多少行閱讀,因此要 使用「而」你一定要做,而裏面的東西,以防止1) 忙着等待2)結束條件。例如:

while(!end) 
{ 
    consoleOutput.mark(32); 
    if (consoleOutput.read()==0x03) end = true;//End of Text 
    else 
    { 
    consoleOutput.reset(); 
    consoleOutput.readLine(); 
    end = false; 
    } 
} 

要處理來自其他線程你在出,你可以使用#non-blocking-buffer

看看在jsch examples

此外,作爲設計建議,您可以使用UserInfo接口來傳遞您的憑證,而不是直接從您的UI對象。

與你類似的項目(基於網頁,不是android):https://github.com/kohsuke/ajaxterm4j