Linux下通过ping判断机器有没有外网。(不用root)

博客 分享
0 177
张三
张三 2022-03-30 11:57:18
悬赏:0 积分 收藏

Linux 下通过ping判断机器有没有外网。(不用root)

背景:

想实现一个判断当前系统有没有外网的方法,想到了两种思路:

1)实现一个ICMP协议。但是这个需要root权限才能运行。可以参考:https://www.cnblogs.com/xcywt/p/16070814.html

2)通过ping指令,解析ping的结果来判断有没有网。

 

代码:

0)命令:system("ping 192.168.1.21 -c 2 > PingTempTest.txt");   //   -c 2 表示ping两次。

1)再去解析PingTempTest.txt中的内容。

3)实际使用时由于ping是耗时操作,为了不阻塞主线程,开了一个子线程去调用ping。

4)注意:如果系统是中文版本,可能ping运行的结果格式不一致。将无法使用下面的解析方法。

5)编译时需要指定C++14,和链接线程库。

头文件:

/* * @author:xcywt * @date:2022-03-30 * @contact me: https://www.cnblogs.com/xcywt/ */#ifndef __DDR_CHECKFOREXTRANET_H__#define __DDR_CHECKFOREXTRANET_H__#include <string>namespace DDRSys{    /*        检测有没有外网的。原理就是:尝试ping某个ip,然后解析ping的结果。        每次创建一个对象会开辟一个线程。在线程中循环ping。        可以通过 GetNetState 取得结果。        测试系统:ubuntu16.04        用法:         void test_20220330()        {            DDRSys::CheckForExtranet check;            check.SetPingIntervals(10);            //check.SetPingIp("114.114.114.114");            //check.SetPingIp("114.114.114.11");            //check.SetPingIp("8.8.8.8");            //check.SetPingIp("8.8.8.7");            check.SetPingIp("192.168.1.21");            int nnn = 0;            while (1)            {                nnn++;                //printf("test_20220330() nnn:%d State:%d\n", nnn, check.GetNetState());                std::this_thread::sleep_for(std::chrono::milliseconds(2000));                if (nnn > 100)                    break;            }        }        编译时需要指定C++14,和链接线程库。        g++ main.cpp CheckForExtranet.cpp -std=c++14  -lpthread    */        class CheckForExtranet    {    public:        CheckForExtranet();        ~CheckForExtranet();        // 设置需要ping的ip,一般指定 8.8.8.8 或者 114.114.114.114        void SetPingIp(std::string ip);        // 设置间隔时间。单位为秒。设置为10,表示每隔10秒尝试ping一次        void SetPingIntervals(int sec);        // -1:表示无效值  0:没网  1:有网        int GetNetState();    private:        class IMPL;        IMPL *m_pImp = nullptr;    };}#endif // __DDR_CHECKFOREXTRANET_H__

源文件:

#include "CheckForExtranet.h"#include <thread>#include <mutex>#include <fstream>#include <vector>namespace DDRSys{    std::vector<std::string> split(const std::string &text, char sep)    {        std::vector<std::string> tokens;        std::size_t start = 0, end = 0;        while ((end = text.find(sep, start)) != std::string::npos) {            if (end != start) {                tokens.emplace_back(text.substr(start, end - start));            }            start = end + 1;        }        if (end != start) {            tokens.emplace_back(text.substr(start));        }        return tokens;    }    class CheckForExtranet::IMPL    {    public:        IMPL()         {            m_subThread = std::thread(subThread, (void*)this);        }        ~IMPL()        {            printf("[%s] CheckForExtranet::IMPL::~IMPL() +++ \n", GetLogPrev().c_str());            if (1)            {                std::lock_guard<std::mutex> lll(m_mutex);                m_bQuit = true;            }            if (m_subThread.joinable())            {                std::this_thread::sleep_for(std::chrono::milliseconds(2000));                m_subThread.join();            }            printf("[%s] CheckForExtranet::IMPL::~IMPL() --- \n", GetLogPrev().c_str());        }        std::string GetLogPrev()        {            return "ExtranetLog";            //return DDRSys::GetCurTimeStamp_MilSec(); // 这个函数返回当时时间戳的        }        void SetPingIp(std::string ip)        {            std::lock_guard<std::mutex> lll(m_mutex);            m_strPingIp = ip;        }        void SetPingIntervals(int sec)        {            std::lock_guard<std::mutex> lll(m_mutex);            m_Intervals = sec;        }        int GetNetState()        {            std::lock_guard<std::mutex> lll(m_mutex);            auto curr = m_nState;            return curr;        }        void _myLoop()        {            printf("[%s] CheckForExtranet::IMPL::_myLoop() +++ \n", GetLogPrev().c_str());            const int waitTime = 500;            int waitCount = -1;            while (1)            {                int Intervals = 0;                bool bQuit = false;                if (1)                {                    std::lock_guard<std::mutex> lll(m_mutex);                    bQuit = m_bQuit;                    Intervals = m_Intervals;                }                if (bQuit)                {                    break;                }                std::this_thread::sleep_for(std::chrono::milliseconds(waitTime));                if ((waitCount > (m_Intervals * 1000) / waitTime) || (waitCount < 0))                {                    waitCount = 0;                    Ping();                }                waitCount++;            }            printf("[%s] CheckForExtranet::IMPL::_myLoop() --- \n", GetLogPrev().c_str());        }        static void subThread(void *param)        {            if (param)            {                auto *pThis = (CheckForExtranet::IMPL*)param;                pThis->_myLoop();            }        }        void Ping()        {                        std::string strip = "";            if (1)            {                std::lock_guard<std::mutex> lll(m_mutex);                strip = m_strPingIp;            }            std::string fileNameTemp("PingTempTest");            fileNameTemp += ".txt";            std::string cmd("ping ");            cmd += strip;            cmd += " -c 2 > ";            cmd += fileNameTemp;            printf("[%s] Start ping:%s cmd:[%s] ++++ \n", GetLogPrev().c_str(),strip.c_str(), cmd.c_str());            system(cmd.c_str());            // cmd eg:ping 192.168.1.21 -c 2 > PingTempTest.txt            // 这里是解析上面的结果。如果系统是中文版本,可能ping运行的结果格式不一致。将无法使用下面的解析方法。            int state = -1;            std::vector<std::string> vecTTT;            std::ifstream in(fileNameTemp.c_str());            if (in.is_open())            {                std::string s;                while (getline(in, s))                {                    vecTTT.push_back(s);                }                in.close();            }            for (auto item : vecTTT)            {                if ((int)item.find("packet loss") > 0)                {                    // 2 packets transmitted, 0 received, 100% packet loss, time 1001ms                    auto vec = split(item, ','); // 这个函数是分隔用的。根据逗号分隔,结果放在vec中。                    for (auto ii : vec)                    {                        if ((int)ii.find("packet loss") > 0)                        {                            int index = ii.find("%");                            std::string str;                            str.assign(ii.begin(), ii.begin() + index);                            int packetLoss = std::atoi(str.c_str());                            if (packetLoss >= 80)                                state = 0; // 丢失率大于80%就认为是没网了                            else                                state = 1;                            printf("[%s] ReadInfo:%s packetLoss:%d state:%d\n", GetLogPrev().c_str(), ii.c_str(), packetLoss, state);                            break;                        }                    }                    break;                }            }            /*            dadao@dadao:~$ ping 8.8.8.8 -c 2            PING 8.8.8.8 (8.8.8.8) 56(84) bytes of data.            64 bytes from 8.8.8.8: icmp_seq=1 ttl=116 time=48.8 ms            64 bytes from 8.8.8.8: icmp_seq=2 ttl=116 time=50.3 ms            --- 8.8.8.8 ping statistics ---            2 packets transmitted, 2 received, 0% packet loss, time 1001ms            rtt min/avg/max/mdev = 48.893/49.609/50.326/0.750 ms            dadao@dadao:~$ ping 8.8.8.82 -c 2            PING 8.8.8.82 (8.8.8.82) 56(84) bytes of data.            --- 8.8.8.82 ping statistics ---            2 packets transmitted, 0 received, 100% packet loss, time 1001ms            dadao@dadao:~$            */            if (1)            {                std::lock_guard<std::mutex> lll(m_mutex);                m_nState = state;            }            std::this_thread::sleep_for(std::chrono::milliseconds(10));                        printf("[%s] End ping:%s state:%d ---- \n", GetLogPrev().c_str(), strip.c_str(), state);        }    private:        std::thread m_subThread;        std::mutex m_mutex;        bool m_bQuit = false;        int m_nState = -1; // // -1表示结果无意义   0表示没网  1表示有网        std::string m_strPingIp = "8.8.8.8";        int m_Intervals = 10;    };        CheckForExtranet::CheckForExtranet()    {        m_pImp = new CheckForExtranet::IMPL();    }    CheckForExtranet::~CheckForExtranet()    {        if (m_pImp)        {            m_pImp->~IMPL();            m_pImp = nullptr;        }    }    void CheckForExtranet::SetPingIp(std::string ip)    {        if (m_pImp)        {            m_pImp->SetPingIp(ip);        }    }    void CheckForExtranet::SetPingIntervals(int sec)    {        if (m_pImp)        {            m_pImp->SetPingIntervals(sec);        }    }    int CheckForExtranet::GetNetState()    {        if (m_pImp)        {            return m_pImp->GetNetState();        }        return -1;    }}

 

实际效果:

dadao@dadao:~/workspace/test/PIng$ ./a.out
[ExtranetLog] CheckForExtranet::IMPL::_myLoop() +++
[ExtranetLog] Start ping:192.168.1.21 cmd:[ping 192.168.1.21 -c 2 > PingTempTest.txt] ++++
[ExtranetLog] ReadInfo: 0% packet loss packetLoss:0 state:1
[ExtranetLog] End ping:192.168.1.21 state:1 ----
[ExtranetLog] Start ping:192.168.1.21 cmd:[ping 192.168.1.21 -c 2 > PingTempTest.txt] ++++
[ExtranetLog] ReadInfo: 0% packet loss packetLoss:0 state:1
[ExtranetLog] End ping:192.168.1.21 state:1 ----

 

posted @ 2022-03-30 11:51 xcywt 阅读(0) 评论(0) 编辑 收藏 举报
回帖
    张三

    张三 (王者 段位)

    821 积分 (2)粉丝 (41)源码

     

    温馨提示

    亦奇源码

    最新会员