1. <strong id="7actg"></strong>
    2. <table id="7actg"></table>

    3. <address id="7actg"></address>
      <address id="7actg"></address>
      1. <object id="7actg"><tt id="7actg"></tt></object>

        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ù)器是否在線(xiàn),需要用到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)
        1. <strong id="7actg"></strong>
        2. <table id="7actg"></table>

        3. <address id="7actg"></address>
          <address id="7actg"></address>
          1. <object id="7actg"><tt id="7actg"></tt></object>
            男男一区二区三区 | 国产一二三在线播放 | 不要播放器看黄色片 | 91无码人妻精品一区二区三区四 | 91对白 | 免费三级网| 77777亚洲和欧洲 | 91艹逼 | 久久久久久97 | 国产成人在线综合豆花 |