org.apache.commons.net.MalformedServerReplyException: Could not parse response code. Server Reply: SSH-2.0-SSH


1、使用commons-net連接ftp報錯,如下所示:

 1 org.apache.commons.net.MalformedServerReplyException: Could not parse response code.
 2 Server Reply: SSH-2.0-SSH
 3     at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:344)
 4     at org.apache.commons.net.ftp.FTP.__getReply(FTP.java:300)
 5     at org.apache.commons.net.ftp.FTP._connectAction_(FTP.java:438)
 6     at org.apache.commons.net.ftp.FTPClient._connectAction_(FTPClient.java:962)
 7     at org.apache.commons.net.ftp.FTPClient._connectAction_(FTPClient.java:950)
 8     at org.apache.commons.net.SocketClient._connect(SocketClient.java:244)
 9     at org.apache.commons.net.SocketClient.connect(SocketClient.java:202)
10     at com.fline.security.adaptation.utils.FtpUtils.uploadFile(FtpUtils.java:63)
11     at com.fline.security.adaptation.utils.FtpUtils.main(FtpUtils.java:29)

其中,使用的commons-net的maven依賴,如下所示:

1 <!-- https://mvnrepository.com/artifact/commons-net/commons-net -->
2 <dependency>
3     <groupId>commons-net</groupId>
4     <artifactId>commons-net</artifactId>
5     <version>3.6</version>
6 </dependency>

案例代碼,參考:https://blog.csdn.net/tengdazhang770960436/article/details/43237369,如下所示:

  1 package com.fline.security.adaptation.utils;
  2 
  3 import java.io.File;
  4 import java.io.FileInputStream;
  5 import java.io.FileOutputStream;
  6 import java.io.IOException;
  7 import java.io.InputStream;
  8 import java.io.OutputStream;
  9 
 10 import org.apache.commons.net.ftp.FTPClient;
 11 import org.apache.commons.net.ftp.FTPFile;
 12 import org.apache.commons.net.ftp.FTPReply;
 13 
 14 public class FtpUtils {
 15 
 16     public static void main(String[] args) throws Exception {
 17 
 18 //        // =======上傳測試============
 19         String localFile = "C:\\Users\\bhlgo\\Downloads\\中國.txt";
 20 
 21         String url = "ip地址";
 22         int port = 端口號;
 23         String username = "賬號";
 24         String password = "密碼";
 25         String path = "目錄";
 26         String filename = "中國.txt";
 27         InputStream input = new FileInputStream(new File(localFile));
 28 
 29         uploadFile(url, port, username, password, path, filename, input);
 30 //        // =======上傳測試============
 31 
 32         // =======下載測試============
 33 //        String localPath = "D:\\";
 34 //        String url = "192.168.120.133";
 35 //        int port = 21;
 36 //        String username ="ftpuser";
 37 //        String password ="ftpuser";
 38 //        String remotePath ="/data/admftp/kw";
 39 //        String fileName = "test.txt";
 40 //        downFile(url, port, username, password, remotePath, fileName, localPath);
 41         // =======下載測試============
 42 
 43     }
 44 
 45     /**
 46      * Description: 向FTP服務器上傳文件
 47      * 
 48      * @param url      FTP服務器 hostname
 49      * @param port     FTP服務器端口 默認端 21
 50      * @param username FTP登錄賬號
 51      * @param password FTP登錄密碼
 52      * @param path     FTP服務器保存目錄
 53      * @param filename 上傳到FTP服務器上的文件名
 54      * @param input    輸入流
 55      * @return 成功返回true,否則返回false
 56      */
 57     public static boolean uploadFile(String url, int port, String username, String password, String path,
 58             String filename, InputStream input) {
 59         boolean success = false;
 60         FTPClient ftp = new FTPClient();
 61         try {
 62             int reply;
 63             ftp.connect(url, port);// 連接FTP服務器
 64 //            ftp.connect(url);//連接FTP服務器 
 65             // 如果采用默認端口,可以使用ftp.connect(url)的方式直接連接FTP服務器
 66             ftp.login(username, password);// 登錄
 67 //            ftp.setFileType(FTPClient.BINARY_FILE_TYPE);
 68 //            ftp.setControlEncoding("GBK");
 69             reply = ftp.getReplyCode();
 70             if (!FTPReply.isPositiveCompletion(reply)) {
 71                 ftp.disconnect();
 72                 return success;
 73             }
 74             ftp.changeWorkingDirectory(path);
 75             // 設置文件名上傳的編碼格式為 utf-8
 76             ftp.storeFile(new String(filename.getBytes("utf-8"), "iso-8859-1"), input);
 77 
 78             input.close();
 79             ftp.logout();
 80             success = true;
 81         } catch (IOException e) {
 82             e.printStackTrace();
 83         } finally {
 84             if (ftp.isConnected()) {
 85                 try {
 86                     ftp.disconnect();
 87                 } catch (IOException ioe) {
 88                 }
 89             }
 90         }
 91         return success;
 92     }
 93 
 94     /**
 95      * Description: 從FTP服務器下載文件
 96      * 
 97      * @param url        FTP服務器hostname
 98      * @param port       FTP服務器端口
 99      * @param username   FTP登錄賬號
100      * @param password   FTP登錄密碼
101      * @param remotePath FTP服務器上的相對路徑
102      * @param fileName   要下載的文件名
103      * @param localPath  下載后保存到本地的路徑
104      * @return
105      */
106     public static boolean downFile(String url, int port, String username, String password, String remotePath,
107             String fileName, String localPath) {
108         boolean success = false;
109         FTPClient ftp = new FTPClient();
110         try {
111             int reply;
112             ftp.connect(url, port);
113             // 如果采用默認端口,可以使用ftp.connect(url)的方式直接連接FTP服務器
114             ftp.login(username, password);// 登錄
115             reply = ftp.getReplyCode();
116             if (!FTPReply.isPositiveCompletion(reply)) {
117                 ftp.disconnect();
118                 return success;
119             }
120             ftp.changeWorkingDirectory(remotePath);// 轉移到FTP服務器目錄
121             FTPFile[] fs = ftp.listFiles();
122             for (FTPFile ff : fs) {
123                 String remotFileName = new String(ff.getName().getBytes("iso-8859-1"), "utf-8");
124                 if (remotFileName.equals(fileName)) {
125                     File localFile = new File(localPath + "/" + remotFileName);
126                     OutputStream is = new FileOutputStream(localFile);
127                     ftp.retrieveFile(ff.getName(), is);
128                     is.close();
129                 }
130             }
131 
132             ftp.logout();
133             success = true;
134         } catch (IOException e) {
135             e.printStackTrace();
136         } finally {
137             if (ftp.isConnected()) {
138                 try {
139                     ftp.disconnect();
140                 } catch (IOException ioe) {
141                 }
142             }
143         }
144         return success;
145     }
146 
147 }

2、解決方法

  使用com.jcraft.jsch.JSch提供的SSH解決方法,參考:https://www.cnblogs.com/biehongli/p/9780652.html。代碼如下:

  1 package com.fline.aic.utils;
  2 
  3 import java.io.BufferedReader;
  4 import java.io.File;
  5 import java.io.FileInputStream;
  6 import java.io.FileNotFoundException;
  7 import java.io.IOException;
  8 import java.io.InputStream;
  9 import java.io.InputStreamReader;
 10 import java.util.Properties;
 11 import java.util.Vector;
 12 
 13 import com.jcraft.jsch.Channel;
 14 import com.jcraft.jsch.ChannelExec;
 15 import com.jcraft.jsch.ChannelSftp;
 16 import com.jcraft.jsch.JSch;
 17 import com.jcraft.jsch.JSchException;
 18 import com.jcraft.jsch.Session;
 19 import com.jcraft.jsch.SftpException;
 20 
 21 /**
 22  *
 23  * @Description TODO
 24  * @author biehl
 25  * @Date 2018年10月11日 上午10:20:11
 26  *
 27  * 說明:exec用於執行命令;sftp用於文件處理
 28  */
 29 public class SSHRemoteCall {
 30 
 31     // 私有的對象
 32     private static SSHRemoteCall sshRemoteCall;
 33 
 34     /**
 35      * 私有的構造方法
 36      */
 37     private SSHRemoteCall() {
 38     }
 39 
 40     // 懶漢式,線程不安全,適合單線程
 41     public static SSHRemoteCall getInstance() {
 42         if (sshRemoteCall == null) {
 43             sshRemoteCall = new SSHRemoteCall();
 44         }
 45         return sshRemoteCall;
 46     }
 47 
 48     // 懶漢式,線程安全,適合多線程
 49     public static synchronized SSHRemoteCall getInstance2() {
 50         if (sshRemoteCall == null) {
 51             sshRemoteCall = new SSHRemoteCall();
 52         }
 53         return sshRemoteCall;
 54     }
 55 
 56     private static final int DEFAULT_PORT = 22;// 默認端口號
 57     private int port;// 端口號
 58 
 59     private static String ipAddress = "192.168.110.130";// ip地址
 60     private static String userName = "root";// 賬號
 61     private static String password = "hadoop";// 密碼
 62 
 63     private Session session;// JSCH session
 64     private boolean logined = false;// 是否登陸
 65 
 66     /**
 67      * 構造方法,可以直接使用DEFAULT_PORT
 68      *
 69      * @param ipAddress
 70      * @param userName
 71      * @param password
 72      */
 73     public SSHRemoteCall(String ipAddress, String userName, String password) {
 74         this(ipAddress, DEFAULT_PORT, userName, password);
 75     }
 76 
 77     /**
 78      * 構造方法,方便直接傳入ipAddress,userName,password進行調用
 79      *
 80      * @param ipAddress
 81      * @param port
 82      * @param userName
 83      * @param password
 84      */
 85     public SSHRemoteCall(String ipAddress, int port, String userName, String password) {
 86         super();
 87         this.ipAddress = ipAddress;
 88         this.userName = userName;
 89         this.password = password;
 90         this.port = port;
 91     }
 92 
 93     /**
 94      * 遠程登陸
 95      *
 96      * @throws Exception
 97      */
 98     public void sshRemoteCallLogin(String ipAddress, String userName, String password) throws Exception {
 99         // 如果登陸就直接返回
100         if (logined) {
101             return;
102         }
103         // 創建jSch對象
104         JSch jSch = new JSch();
105         try {
106             // 獲取到jSch的session, 根據用戶名、主機ip、端口號獲取一個Session對象
107             session = jSch.getSession(userName, ipAddress, DEFAULT_PORT);
108             // 設置密碼
109             session.setPassword(password);
110 
111             // 方式一,通過Session建立連接
112             // session.setConfig("StrictHostKeyChecking", "no");
113             // session.connect();
114 
115             // 方式二,通過Session建立連接
116             // java.util.Properties;
117             Properties config = new Properties();
118             config.put("StrictHostKeyChecking", "no");
119             session.setConfig(config);// 為Session對象設置properties
120             // session.setTimeout(3000);// 設置超時
121             session.connect();//// 通過Session建立連接
122 
123             // 設置登陸狀態
124             logined = true;
125         } catch (JSchException e) {
126             // 設置登陸狀態為false
127             logined = false;
128             throw new Exception(
129                     "主機登錄失敗, IP = " + ipAddress + ", USERNAME = " + userName + ", Exception:" + e.getMessage());
130         }
131     }
132 
133     /**
134      * 關閉連接
135      */
136     public void closeSession() {
137         // 調用session的關閉連接的方法
138         if (session != null) {
139             // 如果session不為空,調用session的關閉連接的方法
140             session.disconnect();
141         }
142 
143     }
144 
145     /**
146      * 執行相關的命令
147      *
148      * @param command
149      * @throws IOException
150      */
151     public void execCommand(String command) throws IOException {
152         InputStream in = null;// 輸入流(讀)
153         Channel channel = null;// 定義channel變量
154         try {
155             // 如果命令command不等於null
156             if (command != null) {
157                 // 打開channel
158                 //說明:exec用於執行命令;sftp用於文件處理
159                 channel = session.openChannel("exec");
160                 // 設置command
161                 ((ChannelExec) channel).setCommand(command);
162                 // channel進行連接
163                 channel.connect();
164                 // 獲取到輸入流
165                 in = channel.getInputStream();
166                 // 執行相關的命令
167                 String processDataStream = processDataStream(in);
168                 // 打印相關的命令
169                 System.out.println("1、打印相關返回的命令: " + processDataStream);
170             }
171         } catch (JSchException e) {
172             e.printStackTrace();
173         } catch (IOException e) {
174             e.printStackTrace();
175         } catch (Exception e) {
176             e.printStackTrace();
177         } finally {
178             if (in != null) {
179                 in.close();
180             }
181             if (channel != null) {
182                 channel.disconnect();
183             }
184         }
185 
186     }
187 
188     /**
189      * 對將要執行的linux的命令進行遍歷
190      *
191      * @param in
192      * @return
193      * @throws Exception
194      */
195     public String processDataStream(InputStream in) throws Exception {
196         StringBuffer sb = new StringBuffer();
197         BufferedReader br = new BufferedReader(new InputStreamReader(in));
198         String result = "";
199         try {
200             while ((result = br.readLine()) != null) {
201                 sb.append(result);
202                 // System.out.println(sb.toString());
203             }
204         } catch (Exception e) {
205             throw new Exception("獲取數據流失敗: " + e);
206         } finally {
207             br.close();
208         }
209         return sb.toString();
210     }
211 
212     /**
213      * 上傳文件 可參考:https://www.cnblogs.com/longyg/archive/2012/06/25/2556576.html
214      *
215      * @param directory
216      *            上傳文件的目錄
217      * @param uploadFile
218      *            將要上傳的文件
219      */
220     public void uploadFile(String directory, String uploadFile) {
221         try {
222             // 打開channelSftp
223             ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
224             // 遠程連接
225             channelSftp.connect();
226             // 創建一個文件名稱問uploadFile的文件
227             File file = new File(uploadFile);
228             // 將文件進行上傳(sftp協議)
229             // 將本地文件名為src的文件上傳到目標服務器,目標文件名為dst,若dst為目錄,則目標文件名將與src文件名相同.
230             // 采用默認的傳輸模式:OVERWRITE
231             channelSftp.put(new FileInputStream(file), directory, ChannelSftp.OVERWRITE);
232             // 切斷遠程連接
233             channelSftp.exit();
234             System.out.println("2、" + file.getName() + " 文件上傳成功.....");
235         } catch (JSchException e) {
236             e.printStackTrace();
237         } catch (SftpException e) {
238             e.printStackTrace();
239         } catch (FileNotFoundException e) {
240             e.printStackTrace();
241         }
242 
243     }
244 
245     /**
246      * 下載文件 采用默認的傳輸模式:OVERWRITE
247      *
248      * @param src
249      *            linux服務器文件地址
250      * @param dst
251      *            本地存放地址
252      * @throws JSchException
253      * @throws SftpException
254      */
255     public void fileDownload(String src, String dst) throws JSchException, SftpException {
256         // src 是linux服務器文件地址,dst 本地存放地址
257         ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
258         // 遠程連接
259         channelSftp.connect();
260         // 下載文件,多個重載方法
261         channelSftp.get(src, dst);
262         // 切斷遠程連接,quit()等同於exit(),都是調用disconnect()
263         channelSftp.quit();
264         // channelSftp.disconnect();
265         System.out.println("3、" + src + " ,下載文件成功.....");
266     }
267 
268     /**
269      * 刪除文件
270      *
271      * @param directory
272      *            要刪除文件所在目錄
273      * @param deleteFile
274      *            要刪除的文件
275      * @param sftp
276      * @throws SftpException
277      * @throws JSchException
278      */
279     public void deleteFile(String directoryFile) throws SftpException, JSchException {
280         // 打開openChannel的sftp
281         ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
282         // 遠程連接
283         channelSftp.connect();
284         // 刪除文件
285         channelSftp.rm(directoryFile);
286         // 切斷遠程連接
287         channelSftp.exit();
288         System.out.println("4、" + directoryFile + " 刪除的文件.....");
289     }
290 
291     /**
292      * 列出目錄下的文件
293      *
294      * @param directory
295      *            要列出的目錄
296      * @param sftp
297      * @return
298      * @throws SftpException
299      * @throws JSchException
300      */
301     public Vector listFiles(String directory) throws JSchException, SftpException {
302         ChannelSftp channelSftp = (ChannelSftp) session.openChannel("sftp");
303         // 遠程連接
304         channelSftp.connect();
305         // 顯示目錄信息
306         Vector ls = channelSftp.ls(directory);
307         System.out.println("5、" + ls);
308         // 切斷連接
309         channelSftp.exit();
310         return ls;
311     }
312 
313     public static void main(String[] args) {
314         // 連接到指定的服務器
315         try {
316             // 1、首先遠程連接ssh
317             SSHRemoteCall.getInstance().sshRemoteCallLogin(ipAddress, userName, password);
318             // 打印信息
319             System.out.println("0、連接192.168.110.130,ip地址: " + ipAddress + ",賬號: " + userName + ",連接成功.....");
320 
321             // 2、執行相關的命令
322             // 查看目錄信息
323             // String command = "ls /home/hadoop/package ";
324             // 查看文件信息
325             // String command = "cat /home/hadoop/package/test ";
326             // 查看磁盤空間大小
327             // String command = "df -lh ";
328             // 查看cpu的使用情況
329             // String command = "top -bn 1 -i -c ";
330             // 查看內存的使用情況
331             String command = "free ";
332             SSHRemoteCall.getInstance().execCommand(command);
333 
334             // 3、上傳文件
335             String directory = "/home/hadoop/package/poi.xlsx";// 目標文件名
336             String uploadFile = "E:\\poi.xlsx";// 本地文件名
337             SSHRemoteCall.getInstance().uploadFile(directory, uploadFile);
338 
339             // 4、下載文件
340             // src 是linux服務器文件地址,dst 本地存放地址,采用默認的傳輸模式:OVERWRITE
341             //test為文件名稱哈
342             String src = "/home/hadoop/package/test";
343             String dst = "E:\\";
344             SSHRemoteCall.getInstance().fileDownload(src, dst);
345 
346             // 5、刪除文件
347             String deleteDirectoryFile = "/home/hadoop/package/test";
348             SSHRemoteCall.getInstance().deleteFile(deleteDirectoryFile);
349 
350             // 6、展示目錄下的文件信息
351             String lsDirectory = "/home/hadoop/package";
352             SSHRemoteCall.getInstance().listFiles(lsDirectory);
353 
354             // 7、關閉連接
355             SSHRemoteCall.getInstance().closeSession();
356         } catch (Exception e) {
357             // 打印錯誤信息
358             System.err.println("遠程連接失敗......");
359             e.printStackTrace();
360         }
361     }
362 
363 }

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM