前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
MCP广场
社区首页 >专栏 >Linux 下通过ping判断机器有没有外网。(不用root)

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

作者头像
xcywt
发布于 2022-05-09 06:27:53
发布于 2022-05-09 06:27:53
1.7K00
代码可运行
举报
文章被收录于专栏:xcywtxcywt
运行总次数:0
代码可运行

背景:

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

1)实现一个ICMP协议。但是这个需要root权限才能运行。可以参考:https://cloud.tencent.com/developer/article/1996958

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,和链接线程库。

头文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
/*
 * @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__

源文件:

代码语言:javascript
代码运行次数:0
运行
AI代码解释
复制
#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 ----

本文参与 腾讯云自媒体同步曝光计划,分享自作者个人站点/博客。
原始发表:2022-03-30,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体同步曝光计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
暂无评论
推荐阅读
编辑精选文章
换一批
C++11新特性之线程操作
  C++11之前没有对并发编程提供语言级别的支持,这使得我们在编写可移植的并发程序时,存在诸多的不便。现在C++11增加了线程以及线程相关的类,很方便地支持了并发编程,使得编写的多线程程序的可移植性得到了很大的提高。
全栈程序员站长
2022/07/18
5860
C++ 中文周刊 2025-02-01 第177期
如果if里的nickName存在等于nullptr的可能,那么memcpy的行为会有UB,那么这个代码必然有问题了
王很水
2025/02/04
510
C++ 中文周刊 2025-02-01 第177期
Zookeeper C++编程实战之配置更新
CZookeeperHelper: https://github.com/eyjian/libmooon/blob/master/include/mooon/net/zookeeper_helper.h CMainHelper: https://github.com/eyjian/libmooon/blob/master/include/mooon/sys/main_template.h
一见
2018/12/13
1.4K0
C++ 中文周刊 第80期
从reddit/hackernews/lobsters/meetingcpp知乎等等摘抄一些c++动态
王很水
2022/09/23
2910
C++:thread | condition_variable|mutex
相信大家在Linux系统编程中都接触过线程创建和退出的相关系统调用,这些系统调用是Linux环境下的一套线程设计方案。但是这种设计方案仅限于Linux环境下使用,其缺点就是可移植性差。所以C++设计了thread库,该库可以适用于任何平台下,从根本上解决了可移植性差的问题。
破晓的历程
2024/10/10
1630
大华摄像头暴破工具bruteforceCamera
大家好,我是余老师。今天有小伙伴有需求,所以写了个小工具,用于摄像头密码爆破。文末会给出下载地址,后续有需求会持续更新版本。
白帽子安全笔记
2024/10/28
7545
大华摄像头暴破工具bruteforceCamera
【C++】C++11线程库 和 C++IO流
1. C++11的线程库实际封装了windows和linux底层的原生线程库接口,在不同的操作系统下运行时,C++11线程库可以通过条件编译的方式来适配的使用不同的接口,比如在linux下,就用封装POSIX线程库的接口来进行多线程编程,在windows下,就用封装WinAPI线程库的接口来进行多线程编程。所以C++11线程库为我们带来了可移植性编程。
举杯邀明月
2023/10/17
4120
【C++】C++11线程库 和 C++IO流
【C++】基础:获取ping的时延数据示例
PING是一种常用的网络工具,用于测试计算机之间的连接状况和测量网络时延。它发送一个小的数据包到目标计算机,并等待接收响应。通过测量从发送到接收的时间差,可以得出网络延迟或往返时间(Round-Trip Time, RTT),即从发送请求到获取响应的时间。
DevFrank
2024/07/24
3480
(五)如何编写高性能日志
一、服务器端日志与客户端日志的区别 在正式讲解之前,我们先来看一个日志类的实现方法,这个日志类也是代表着大多数客户端日志的主流写法: /** *@desc: 程序运行log类,log.h *@author: zhangyl *@date: 2017.01.17 **/ #ifndef __LOG_H__ #define __LOG_H__ #ifdef _ZYL_LOG_ #define LogInfo(...) Log::GetInstance(
范蠡
2018/04/04
1.5K0
asio 调度器实现 - strand 实现详解
只有一个线程在执行scheduler::run() 的情况, 我们不需要担心任务执行的先后顺序,它们始终是严格按照post()的先后顺序来执行的. 那么如果我们更多的利用多核, 使用多个线程执行同一个
fangfang
2023/05/23
1.3K0
mysql 连接池的实现
涉及后端的数据交互管理的时候,我们在应用层总是希望将一些过程进行封装进行规模化管理,池化技术基本就是来干这种事情的,线程池,内存池,连接池,请求池等等都是来干这种事情的,当然如果从算法层面来说,这种就是用空间来换时间的做法。我们的很多著名的算法也是基于这样的方式来优化的,著名的 KMP 算法,通过维护一个 next 数组,来降低算法的时间复杂度。
ge3m0r
2024/05/26
2650
微服务开源框架TARS 之 基础组件
本文源自herman的系列文章之一《鹅厂开源框架TARS之基础组件》。相关代码已按TARS开源社区最新版本更新。
TARS基金会
2020/09/01
1.2K0
微服务开源框架TARS 之 基础组件
通过edge://tracing工具进行C++的可视化基准测试
在测试函数类构建一个Timer对象让他开始计时,再离开函数作用时会自动调用析构函数停止计时并且输出耗时结果
晨星成焰
2024/01/29
6232
通过edge://tracing工具进行C++的可视化基准测试
跟面试官刚同步异步编程,有她完全够用了
并行化业务逻辑:经常需要频繁的发送,等待,接收其他业务线程的数据,信息交换是常见且高频的行为,这个时候就要开发高效的异步编程了。
用户9831583
2022/06/16
6050
跟面试官刚同步异步编程,有她完全够用了
心跳包机制设计详解
情形一:一个客户端连接服务器以后,如果长期没有和服务器有数据来往,可能会被防火墙程序关闭连接,有时候我们并不想要被关闭连接。例如,对于一个即时通讯软件,如果服务器没有消息时,我们确实不会和服务器有任何数据交换,但是如果连接被关闭了,有新消息来时,我们再也没法收到了,这就违背了“即时通讯”的设计要求。
范蠡
2019/08/09
7.3K0
C++并发编程(C++11到C++17)
大型的软件项目常常包含非常多的任务需要处理。例如:对于大量数据的数据流处理,或者是包含复杂GUI界面的应用程序。如果将所有的任务都以串行的方式执行,则整个系统的效率将会非常低下,应用程序的用户体验会非常的差。
范蠡
2021/07/16
1.5K0
基于C++实现的EventLoop与事件驱动编程
事件驱动编程(Event-Driven)是一种编码范式,常被应用在图形用户界面,应用程序,服务器开发等场景。
Coder-ZZ
2024/05/09
1.7K0
基于C++实现的EventLoop与事件驱动编程
C++舆情监控爬虫程序实现
如果用C++写一个舆情监控的爬虫程序。我们得要考虑C++在这方面的优势,比如性能高,适合处理大量数据。如果大家对C++的网络库不太熟悉,需要选择合适的库,比如libcurl或者Boost.Beast。然后得解析HTML,可能需要用到Gumbo或者类似的解析库。
华科云商小徐
2025/05/12
1040
如何在Native层设计一个消息队列
做过Android开发的同学对Handler、Looper、MessageQueue、Message应该是非常熟悉了,Android是一个基于消息驱动的系统,我们在日常开发中用到消息队列的地方非常多。Android也给我们封装好了一个强大易用的消息处理API,音视频开发核心逻辑都会放在Native层,我们也希望在C++层实现这样的消息队列。
马上就说
2022/05/25
4940
如何在Native层设计一个消息队列
[源码解析] 机器学习参数服务器ps-lite(2) ----- 通信模块Van
[源码解析] 机器学习参数服务器ps-lite 之(1) ----- PostOffice
罗西的思考
2021/08/06
1.1K0
相关推荐
C++11新特性之线程操作
更多 >
领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档
本文部分代码块支持一键运行,欢迎体验
本文部分代码块支持一键运行,欢迎体验