<kbd id="afajh"><form id="afajh"></form></kbd>
<strong id="afajh"><dl id="afajh"></dl></strong>
    <del id="afajh"><form id="afajh"></form></del>
        1. <th id="afajh"><progress id="afajh"></progress></th>
          <b id="afajh"><abbr id="afajh"></abbr></b>
          <th id="afajh"><progress id="afajh"></progress></th>

          Java 實(shí)現(xiàn) Ping 功能

          共 1578字,需瀏覽 4分鐘

           ·

          2021-02-03 07:20

          公眾號(hào)關(guān)注?“GitHub今日熱榜
          設(shè)為 “星標(biāo)”,帶你挖掘更多開(kāi)發(fā)神器!





          在項(xiàng)目中需要判斷目錄服務(wù)器是否在線,需要用到ping命令。


          為了使用java來(lái)實(shí)現(xiàn)ping的功能,有人推薦使用java的 Runtime.exec()方法來(lái)直接調(diào)用系統(tǒng)的Ping命令,也有人完成了純Java實(shí)現(xiàn)Ping的程序,使用的是Java的NIO包(native io, 高效IO包)。但是設(shè)備檢測(cè)只是想測(cè)試一個(gè)遠(yuǎn)程主機(jī)是否可用。所以,可以使用以下三種方式來(lái)實(shí)現(xiàn):?


          1.使用InetAddress實(shí)現(xiàn)Ping


          public?static?boolean?ping(String ipAddress)?throws?Exception {
          ????int??timeOut = 3000?; //超時(shí)應(yīng)該在3鈔以上
          ????boolean?status = InetAddress.getByName(ipAddress).isReachable(timeOut);
          ????// 當(dāng)返回值是true時(shí),說(shuō)明host是可用的,false則不可。
          ????return?status;
          }


          isReachable方法在Windows系統(tǒng)平臺(tái)上的實(shí)現(xiàn)(native c)并沒(méi)有使用ICMP,而是全完使用連接echo端口7?的方法。Native的實(shí)現(xiàn)源碼:


          /* 
          ?* Windows implementation of ICMP & RAW sockets is too unreliable for now.
          ?* Therefore it's best not to try it at all and rely only on TCP
          ?* We may revisit and enable this code in the future.
          ?*/
          ??
          ??
          /* Can't create a raw socket, so let's try a TCP socket */??
          ??
          him.sin_port = htons(7); /* Echo */???
          connect_rv = connect(fd, (struct?sockaddr *)&him, len);


          InetAddress.isReachable()通過(guò)試圖連接TCP端口的方法是利用了TCP/IP協(xié)議的三次握手原理,即使對(duì)方機(jī)器在端口上沒(méi)有服務(wù),當(dāng)接收到請(qǐng)求時(shí)會(huì)立刻拒絕,如果對(duì)方機(jī)器不在網(wǎng)絡(luò)上則結(jié)果是超時(shí)!這個(gè)方法的實(shí)現(xiàn)正是利用了這一點(diǎn)。引用OpenJDK 6,isReachable()方法native c實(shí)現(xiàn)的一段注釋?zhuān)?/p>


          /** 
          ?* connection established or refused immediately, either way it means
          ?* we were able to reach the host!
          ?*/


          還有一個(gè)問(wèn)題就是超時(shí)時(shí)間的設(shè)置,受網(wǎng)絡(luò)影響,TCP建立連接的3次握手耗時(shí)不確定,例如:



          3次握手耗時(shí)700ms,如果我們?cè)O(shè)置的超時(shí)時(shí)間比700ms小,返回的也是false,從而造成誤報(bào)。


          2.調(diào)用CMD


          通過(guò)程序調(diào)用類(lèi)似“ping 127.0.0.1 -n 10?-w 3000”的命令,該命令ping10次,等待每個(gè)響應(yīng)的超時(shí)時(shí)間3秒。?網(wǎng)絡(luò)通的情況會(huì)輸出:


          C:\Users\tgg>ping 127.0.0.1 -n 10 -w 3000 正在 Ping 127.0.0.1 具有 32 字節(jié)的數(shù)據(jù): 
          來(lái)自 127.0.0.1 的回復(fù): 字節(jié)=32 時(shí)間<1ms TTL=64 來(lái)自 127.0.0.1 的回復(fù): 字節(jié)=32 時(shí)間<1ms TTL=64
          來(lái)自 127.0.0.1 的回復(fù): 字節(jié)=32 時(shí)間<1ms TTL=64 來(lái)自 127.0.0.1 的回復(fù): 字節(jié)=32 時(shí)間<1ms TTL=64
          來(lái)自 127.0.0.1 的回復(fù): 字節(jié)=32 時(shí)間<1ms TTL=64 來(lái)自 127.0.0.1 的回復(fù): 字節(jié)=32 時(shí)間<1ms TTL=64
          ?來(lái)自 127.0.0.1 的回復(fù): 字節(jié)=32 時(shí)間<1ms TTL=64 來(lái)自 127.0.0.1 的回復(fù): 字節(jié)=32 時(shí)間<1ms TTL=64
          來(lái)自 127.0.0.1 的回復(fù): 字節(jié)=32 時(shí)間<1ms TTL=64 來(lái)自 127.0.0.1 的回復(fù): 字節(jié)=32 時(shí)間<1ms TTL=64
          127.0.0.1 的 Ping 統(tǒng)計(jì)信息: 數(shù)據(jù)包: 已發(fā)送 = 10,已接收 = 10,丟失 = 0 (0% 丟失), 往返行程的估
          計(jì)時(shí)間(以毫秒為單位): 最短 = 0ms,最長(zhǎng) = 0ms,平均 = 0ms


          以上信息輸出是根據(jù)操作系統(tǒng)的語(yǔ)言來(lái)進(jìn)行本地化的,其中"ms TTL="是不變的,我們可以通過(guò)Runtime.exec方法來(lái)調(diào)用本地CMD命令來(lái)執(zhí)行以上語(yǔ)句,代碼如下:


          import?org.apache.log4j.Logger;
          import?java.io.BufferedReader;
          import?java.io.IOException;
          import?java.io.InputStreamReader;
          import?java.net.InetAddress;
          import?java.util.regex.Matcher;
          import?java.util.regex.Pattern;
          /** * @author?tgg */
          ?
          public?class?Ping?{
          ?
          ????public?static?boolean?ping(String ipAddress)?throws?Exception {
          ????????int?timeOut = 3000?;
          ????????boolean?status = InetAddress.getByName(ipAddress).isReachable(timeOut);
          ????????return?status;
          ????}
          ?
          ????public?static?boolean?ping(String ipAddress, int?pingTimes, int?timeOut)?{
          ????????BufferedReader in = null;
          ????????Runtime r = Runtime.getRuntime();
          ????????// 將要執(zhí)行的ping命令,此命令是windows格式的命令
          ????????String pingCommand = "ping "?+ ipAddress + " -n "?+ pingTimes + " -w "?+ timeOut;
          ????????// Linux命令如下
          ????????// String pingCommand = "ping" -c " + pingTimes + " -w " + timeOut + ipAddress;
          ????????try?{
          ????????????if?(logger.isDebugEnabled()) {
          ????????????????logger.debug(pingCommand);
          ????????????}
          ????????????// 執(zhí)行命令并獲取輸出
          ????????????Process p = r.exec(pingCommand);
          ????????????if?(p == null) {
          ????????????????return?false;
          ????????????}
          ????????????in = new?BufferedReader(new?InputStreamReader(p.getInputStream()));
          ????????????int?connectedCount = 0;
          ????????????String line;
          ????????????// 逐行檢查輸出,計(jì)算類(lèi)似出現(xiàn)=23ms TTL=62字樣的次數(shù)
          ????????????while?((line = in.readLine()) != null) {
          ????????????????connectedCount += getCheckResult(line);
          ????????????}
          ????????????// 如果出現(xiàn)類(lèi)似=23ms TTL=62這樣的字樣,出現(xiàn)的次數(shù)=測(cè)試次數(shù)則返回真
          ????????????return?connectedCount == pingTimes;
          ????????} catch?(Exception e) {
          ????????????logger.error(e);
          ????????????return?false;
          ????????} finally?{
          ????????????try?{
          ????????????????in.close();
          ????????????} catch?(IOException e) {
          ????????????????logger.error(e);
          ????????????}
          ????????}
          ????}
          ????//若line含有=18ms TTL=16字樣,說(shuō)明已經(jīng)ping通,返回1,否則返回0.
          ????private?static?int?getCheckResult(String line)?{ // System.out.println("控制臺(tái)輸出的結(jié)果為:"+line);
          ????????Pattern pattern = Pattern.compile("(\\d+ms)(\\s+)(TTL=\\d+)", Pattern.CASE_INSENSITIVE);
          ????????Matcher matcher = pattern.matcher(line);
          ????????while?(matcher.find()) {
          ????????????return?1;
          ????????}
          ????????return?0;
          ????}
          ?
          ????private?static?final?Logger logger = Logger.getLogger(Ping.class);
          }


          3.Java調(diào)用控制臺(tái)執(zhí)行ping命令


          具體的思路是這樣的:


          通過(guò)程序調(diào)用類(lèi)似“ping 127.0.0.1 -n 10 -w 4”的命令,這命令會(huì)執(zhí)行ping十次,如果通順則會(huì)輸出類(lèi)似“來(lái)自127.0.0.1的回復(fù):字節(jié)=32 時(shí)間<1ms TTL=64”的文本(具體數(shù)字根據(jù)實(shí)際情況會(huì)有變化),其中中文是根據(jù)環(huán)境本地化的,有些機(jī)器上的中文部分是英文,但不論是中英文環(huán)境, 后面的“<1ms TTL=62”字樣總是固定的,它表明一次ping的結(jié)果是能通的。如果這個(gè)字樣出現(xiàn)的次數(shù)等于10次即測(cè)試的次數(shù),則說(shuō)明127.0.0.1是百分之百能連通的。?


          技術(shù)上:具體調(diào)用dos命令用Runtime.getRuntime().exec實(shí)現(xiàn),查看字符串是否符合格式用正則表達(dá)式實(shí)現(xiàn)。


          見(jiàn)Ping類(lèi)的ping(String,int,int)函數(shù)。


          import?java.io.BufferedReader;
          import?java.io.IOException;
          import?java.io.InputStreamReader;
          import?java.net.InetAddress;
          import?java.net.UnknownHostException;
          import?java.util.regex.Matcher;
          import?java.util.regex.Pattern;
          ?
          public?class?Ping?{
          ????
          ????public?static?boolean?ping(String ipAddress)?throws?Exception {
          ????????int??timeOut = 3000?; //超時(shí)應(yīng)該在3鈔以上
          ????????boolean?status = InetAddress.getByName(ipAddress).isReachable(timeOut); // 當(dāng)返回值是true時(shí),說(shuō)明host是可用的,false則不可。
          ????????return?status;
          ????}
          ????
          ????public?static?void?ping02(String ipAddress)?throws?Exception {
          ????????String line = null;
          ????????try?{
          ????????????Process pro = Runtime.getRuntime().exec("ping "?+ ipAddress);
          ????????????BufferedReader buf = new?BufferedReader(new?InputStreamReader(
          ????????????????????pro.getInputStream()));
          ????????????while?((line = buf.readLine()) != null)
          ????????????????System.out.println(line);
          ????????} catch?(Exception ex) {
          ????????????System.out.println(ex.getMessage());
          ????????}
          ????}
          ????
          ????public?static?boolean?ping(String ipAddress, int?pingTimes, int?timeOut)?{
          ????????BufferedReader in = null;
          ????????Runtime r = Runtime.getRuntime(); // 將要執(zhí)行的ping命令,此命令是windows格式的命令
          ????????String pingCommand = "ping "?+ ipAddress + " -n "?+ pingTimes + " -w "?+ timeOut;
          ????????try?{ // 執(zhí)行命令并獲取輸出
          ????????????System.out.println(pingCommand);
          ????????????Process p = r.exec(pingCommand);
          ????????????if?(p == null) {
          ????????????????return?false;
          ????????????}
          ????????????in = new?BufferedReader(new?InputStreamReader(p.getInputStream())); // 逐行檢查輸出,計(jì)算類(lèi)似出現(xiàn)=23ms TTL=62字樣的次數(shù)
          ????????????int?connectedCount = 0;
          ????????????String line = null;
          ????????????while?((line = in.readLine()) != null) {
          ????????????????connectedCount += getCheckResult(line);
          ????????????} // 如果出現(xiàn)類(lèi)似=23ms TTL=62這樣的字樣,出現(xiàn)的次數(shù)=測(cè)試次數(shù)則返回真
          ????????????return?connectedCount == pingTimes;
          ????????} catch?(Exception ex) {
          ????????????ex.printStackTrace(); // 出現(xiàn)異常則返回假
          ????????????return?false;
          ????????} finally?{
          ????????????try?{
          ????????????????in.close();
          ????????????} catch?(IOException e) {
          ????????????????e.printStackTrace();
          ????????????}
          ????????}
          ????}
          ????//若line含有=18ms TTL=16字樣,說(shuō)明已經(jīng)ping通,返回1,否則返回0.
          ????private?static?int?getCheckResult(String line)?{ // System.out.println("控制臺(tái)輸出的結(jié)果為:"+line);
          ????????Pattern pattern = Pattern.compile("(\\d+ms)(\\s+)(TTL=\\d+)", Pattern.CASE_INSENSITIVE);
          ????????Matcher matcher = pattern.matcher(line);
          ????????while?(matcher.find()) {
          ????????????return?1;
          ????????}
          ????????return?0;
          ????}
          ????public?static?void?main(String[] args)?throws?Exception {
          ????????String ipAddress = "127.0.0.1";
          ????????System.out.println(ping(ipAddress));
          ????????ping02(ipAddress);
          ????????System.out.println(ping(ipAddress, 5, 5000));
          ????}
          }


          第一種方法:Jdk的InetAddresss,代碼簡(jiǎn)單。
          第二種方法:使用java調(diào)用cmd命令,這種方式最簡(jiǎn)單,可以把ping的過(guò)程顯示在本地。
          第三種方法:也是使用java調(diào)用控制臺(tái)的ping命令,這個(gè)比較可靠,還通用,使用起來(lái)方便:傳入個(gè)ip,設(shè)置ping的次數(shù)和超時(shí),就可以根據(jù)返回值來(lái)判斷是否ping通。


          出處:blog.csdn.net/zeb_perfect/article/details/50133199








          關(guān)注GitHub今日熱榜,專(zhuān)注挖掘好用的開(kāi)發(fā)工具,致力于分享優(yōu)質(zhì)高效的工具、資源、插件等,助力開(kāi)發(fā)者成長(zhǎng)!







          點(diǎn)個(gè)在看 你最好看










          瀏覽 187
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          評(píng)論
          圖片
          表情
          推薦
          點(diǎn)贊
          評(píng)論
          收藏
          分享

          手機(jī)掃一掃分享

          分享
          舉報(bào)
          <kbd id="afajh"><form id="afajh"></form></kbd>
          <strong id="afajh"><dl id="afajh"></dl></strong>
            <del id="afajh"><form id="afajh"></form></del>
                1. <th id="afajh"><progress id="afajh"></progress></th>
                  <b id="afajh"><abbr id="afajh"></abbr></b>
                  <th id="afajh"><progress id="afajh"></progress></th>
                  综合在线第一页 | 色色导航在线 | 亚洲一级黄色视频在线观看 | 中文字幕在线视频无码 | 亚洲 欧美 激情 另类 校园 |