背景:

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

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 ----

Linux 下通过ping判断机器有没有外网。(不用root)的更多相关文章

  1. Windows 和  Linux 下 禁止ping的方法

    Windows 和Linux 下 禁止ping的方法 目的: 禁止网络上的其他主机或服务器ping自己的服务器 运行环境: Windows 03.08  linux 方法: Windows 03下: ...

  2. Linux 下 CPU 使用率与机器负载的关系与区别

    原文链接:  http://blog.chinaunix.net/uid-28541347-id-4926054.html 当我们使用top命令查看系统的资源使用情况时会看到load average, ...

  3. Linux下实现ping功能

    实现ping功能,就肯定要用到ping命令,那么在Linux下ping命令为: ping [-dfnqrRv][-c<完成次数>][-i<间隔秒数>][-I<网络界面&g ...

  4. 虚拟机Linux下解决ping时出现 unknown host问题

    在虚拟机中使用CentOS6.5时,ping www.baidu.com出现报错信息:“ping: unknown hostwww.baidu.com”,虚拟机和物理机网络连接是NAT方式,物理机访问 ...

  5. 扔掉360:Linux下无线网卡作WiFi路由器(转薄荷开源网)

    这个话题很多人感兴趣,毕竟现在是无线互联时代.手机一族到外面去,首先关心的就是有没有 WiFi.Windows 7 用户可以安装 360 的软件,把笔记本电脑配置成路由器,供手机或其他电脑上网. 在 ...

  6. 判断内网机器的真实外网IP或域名的方法总结

    在内渗透中有时需要在某台WEB服务器中留下后门,可以通过内网IP建立IPC连接,但还需要获知外网IP才能访问Wbshell,在无网关权限的情况下,我总结了有如下方法: nslookup myip.op ...

  7. centOS7 可以ping通主机不能访问外网

    前言: 突然打开自己前不久在虚拟机安装的centOS7系统,发现以前可以来联网突然不能访问外网,在网上看了很多方法,终于解决 问题描述: 连上网,但是ping 不同外网,如ping www.baodu ...

  8. VM中Linux网络设置(固定ip、连接外网开发环境)

      在开发过程中,我们经常需要在linux中进行操作.毕竟服务器的系统大多数都是Linux,所以在dev环境需要配置好一台Linux系统配合开发.   在VMWare Workstation Pro中 ...

  9. linux下的ping工具--fping

    前言:       如果想ping 大量的不连续的地址,有想知道放回结果,在linux系统下有一个非常合适的工具--fping. Fping 官网:http://www.fping.org/ Fpin ...

随机推荐

  1. 零基础自学Python十天的时候,写的一款猜数字小游戏,附源码和软件下载链接!

    自学一门语言最重要的是要及时给自己反馈,那么经常写一些小程序培养语感很重要,写完可以总结一下程序中运用到了哪些零散的知识点. 本程序中运用到的知识点有: 1.输入输出函数 (input.print) ...

  2. .Net Core AOP之IResultFilter

    一.简介 在.net core 中Filter分为以下六大类: 1.AuthorizeAttribute(权限验证) 2.IResourceFilter(资源缓存) 3.IActionFilter(执 ...

  3. Bugku--web-wp

    Bugku地址:https://ctf.bugku.com/challenges 0x01 web2 地址:http://123.206.87.240:8002/web2/ ,查看源码 web2 0x ...

  4. 小甲鱼 python——第一课作业!

    0:  python是脚本语言把?虽然不是很清楚什么是脚本语言就是了.复制一下: 脚本语言(英语:Scripting language)是为了缩短传统的"编写.编译.链接.运行"( ...

  5. 业务人员可以进行自助ETL操作?这款BI工具你值得拥有

    ​ETL是什么? ETL,是英文 Extract-Transform-Load 的缩写,用来描述将数据从来源端经过抽取(extract).转换(transform).加载(load)至目的端的过程.E ...

  6. Linux下搭建iSCSI共享存储

    转至:https://www.linuxidc.com/Linux/2016-09/135655.htm Linux下搭建iSCSI共享存储 拓扑: 实验步骤: ------------------- ...

  7. c# winform中TabControl中给每个选项卡添加不同的图标(图片)

    在一个TabControl控件中,有几个选项卡,现在在每个选项卡上显示不同的图标. 1:你要现在form窗体中通过工具箱加入一个imagelist,名字为imagelist1,如下图: 2:然后在里面 ...

  8. vue项目npm run dev报错events.js:160 throw er; // Unhandled 'error' event listen EADDRINUSE :::8002

    出错情况,如下图: 报错原因: listen EADDRINUSE :::8002 意思是当前8002端口被占用 解决办法: 一:简单粗暴:关掉可能影响的相关程序,重新执行启动. 二: 1.Win+R ...

  9. JZ-053-表示数值的字符串

    表示数值的字符串 题目描述 请实现一个函数用来判断字符串是否表示数值(包括整数和小数).例如,字符串"+100","5e2","-123", ...

  10. 使用 Istio CNI 支持强安全 TKE Stack 集群的服务网格流量捕获

    作者 陈计节,企业应用云原生架构师,在腾讯企业 IT 负责云原生应用治理产品的设计与研发工作,主要研究利用容器集群和服务网格等云原生实践模式降低微服务开发与治理门槛并提升运营效率. 摘要 给需要快速解 ...