Java 中執行CMD命令(copy/ping)
java實現一些cmd命令
最近在專案中需要用到一些cmd命令,於是利用java提供的Runtime.getRuntime().exec(cmd)方法執行,現對使用的一些命令做一下小結。:
- 執行copy 命令
- 執行ping命令
執行copy命令
copy命令主要用於複製檔案,在windows環境下,copy命令的格式一般為:copy 原始檔 目的資料夾,比如:copy d:\test\mc2.db e:\test\。
如果想要實現不同主機之間的檔案copy,首先需要保證這兩個主機在網路上是可以連通的,其次可以採取共享檔案的方式,使得執行copy命令的主機能夠直接訪問共享檔案。
需要注意的是,如果在原始檔所在路徑或者目標資料夾路徑中存在空格,這個路徑需要使用雙引號引起來。下面為一個具體的實現例子:
public void copyfile(){
String orig = "\\\\192.168.1.1\\db\\mc2.db"; //原始檔
String dest = "\"D:\\test test\\""; //有空格需要使用雙引號
String cmd = "cmd /c copy"+orig+" "+dest;
try{
Runtime.getRuntime().exec(cmd);
}catch(IOException e){
e.printStackTrace();
}
}
執行ping命令
ping命令主要用於測試與某臺主機的網路連通性,在dos環境下其使用方式比較簡單,只需要按照:ping 目的主機IP地址,比如:ping 192.168.1.1 ,這種方式即可,不過在java中測試主機的連通性不止使用cmd命令這一種。
下面介紹三種在java中測試主機是否連通的方法:
1、使用上面執行cmd命令的方式執行一般的ping命令。
這種方式簡單易行,但是當對端機器開啟防火牆時,這種方式無法成功。
2、簡單的使用 Java 類庫中 java.net.InetAddress 類來實現,這個類提供了兩個方法探測遠端機器是否可達:
isReachable(int timeout)
isReachable(NetworkInterface netif, int ttl, int timeout)
上述方法就是通過遠端機器的IP地址構造InetAddress物件,然後呼叫其isReachable方法,測試呼叫機器和遠端機器的網路可達性。注意到遠端機器可能有多個IP地址,因而可能要迭代的測試所有的情況。
案例1:
isAddressAvailable(String ip){
try{
InetAddress address = InetAddress.getByName(ip);//ping this IP
if(address instanceof java.net.Inet4Address){
System.out.println(ip + " is ipv4 address");
}else
if(address instanceof java.net.Inet6Address){
System.out.println(ip + " is ipv6 address");
}else{
System.out.println(ip + " is unrecongized");
}
if(address.isReachable(5000)){
System.out.println("SUCCESS - ping " + IP + " with no interface specified");
}else{
System.out.println("FAILURE - ping " + IP + " with no interface specified");
}
System.out.println("\n-------Trying different interfaces--------\n");
Enumeration<NetworkInterface> netInterfaces =
NetworkInterface.getNetworkInterfaces();
while(netInterfaces.hasMoreElements()) {
NetworkInterface ni = netInterfaces.nextElement();
System.out.println(
"Checking interface, DisplayName:" + ni.getDisplayName() + ", Name:" + ni.getName());
if(address.isReachable(ni, 0, 5000)){
System.out.println("SUCCESS - ping " + ip);
}else{
System.out.println("FAILURE - ping " + ip);
}
Enumeration<InetAddress> ips = ni.getInetAddresses();
while(ips.hasMoreElements()) {
System.out.println("IP: " + ips.nextElement().getHostAddress());
}
System.out.println("-------------------------------------------");
}
}catch(Exception e){
System.out.println("error occurs.");
e.printStackTrace();
}
}
從上可以看出isReachable的用法,可以不指定任何介面來判斷遠端網路的可達性,但這不能區分出資料包是從那個網路介面發出去的 (如果本地有多個網路介面的話);而高階版本的isReachable則可以指定從本地的哪個網路介面測試,這樣可以準確的知道遠端網路可以連通本地的哪個網路介面。
但是,Java本身沒有提供任何方法來判斷本地的哪個IP地址可以連通遠端網路,Java網路程式設計介面也沒有提供方法來訪問ICMP協議資料包,因而通過ICMP的網路不可達資料包實現這一點也是不可能的 (當然可以用JNI來實現,但就和系統平臺相關了 ), 此時可以考慮本文下一節提出的方法。
3、指定本地和遠端網路地址,判斷兩臺機器之間的可達性
在某些情況下,我們可能要確定本地的哪個網路地址可以連通遠端網路,以便遠端網路可以回連到本地使用某些服務或發出某些通知。一個典型的應用場景是,本地啟動了檔案傳輸服務(如FTP),需要將本地的某個IP地址傳送到遠端機器,以便遠端機器可以通過該地址下載檔案;或者遠端機器提供某些服務,在某些事件發生時通知註冊了獲取這些事件的機器 ( 常見於系統管理領域 ),因而在註冊時需要提供本地的某個可達 (從遠端) 地址。
雖然我們可以用InetAddress.isReachabl方法判斷出本地的哪個網路介面可連通遠端玩過,但是由於單個網路介面是可以配置多個IP地址的,因而在此並不合適。我們可以使用Socket建立可能的TCP連線,進而判斷某個本地 IP 地址是否可達遠端網路。我們使用java.net.Socket 類中的connect方法。
connect(SocketAddress endpoint, int timeout) //使用Socket連線伺服器,指定超時的時間
這種方法需要遠端的某個埠,該埠可以是任何基於TCP協議的開放服務的埠(如一般都會開放的ECHO服務埠7,Linux的SSH服務埠22等)。實際上,建立的TCP連線被協議棧放置在連線佇列,進而分發到真正處理資料的各個應用服務,由於UDP沒有連線的過程,因而基於UDP的服務(如 SNMP)無法在此方法中應用。
具體過程是,列舉本地的每個網路地址,建立本地Socket,在某個埠上嘗試連線遠端地址,如果可以連線上,則說明該本地地址可達遠端網路。
案例2:
printReachableIP(InetAddress remoteAddr, int port){
String retIP = null;
Enumeration<NetworkInterface> netInterfaces;
try{
netInterfaces = NetworkInterface.getNetworkInterfaces();
while(netInterfaces.hasMoreElements()) {
NetworkInterface ni = netInterfaces.nextElement();
Enumeration<InetAddress> localAddrs = ni.getInetAddresses();
while(localAddrs.hasMoreElements()){
InetAddress localAddr = localAddrs.nextElement();
if(isReachable(localAddr, remoteAddr, port, 5000)){
retIP = localAddr.getHostAddress();
break;
}
}
}
} catch(SocketException e) {
System.out.println(
"Error occurred while listing all the local network addresses.");
}
if(retIP == null){
System.out.println("NULL reachable local IP is found!");
}else{
System.out.println("Reachable local IP is found, it is " + retIP);
}
}
boolean isReachable(InetAddress localInetAddr, InetAddress remoteInetAddr,
int port, int timeout) {
booleanisReachable = false;
Socket socket = null;
try{
socket = newSocket();
// 埠號設定為 0 表示在本地挑選一個可用埠進行連線
SocketAddress localSocketAddr = new InetSocketAddress(localInetAddr, 0);
socket.bind(localSocketAddr);
InetSocketAddress endpointSocketAddr =
new InetSocketAddress(remoteInetAddr, port);
socket.connect(endpointSocketAddr, timeout);
System.out.println("SUCCESS - connection established! Local: " +
localInetAddr.getHostAddress() + " remote: " +
remoteInetAddr.getHostAddress() + " port" + port);
isReachable = true;
} catch(IOException e) {
System.out.println("FAILRE - CAN not connect! Local: " +
localInetAddr.getHostAddress() + " remote: " +
remoteInetAddr.getHostAddress() + " port" + port);
} finally{
if(socket != null) {
try{
socket.close();
} catch(IOException e) {
System.out.println("Error occurred while closing socket..");
}
}
}
return isReachable;
}