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 ----
Linux 下通过ping判断机器有没有外网。(不用root)的更多相关文章
- Windows 和 Linux 下 禁止ping的方法
Windows 和Linux 下 禁止ping的方法 目的: 禁止网络上的其他主机或服务器ping自己的服务器 运行环境: Windows 03.08 linux 方法: Windows 03下: ...
- Linux 下 CPU 使用率与机器负载的关系与区别
原文链接: http://blog.chinaunix.net/uid-28541347-id-4926054.html 当我们使用top命令查看系统的资源使用情况时会看到load average, ...
- Linux下实现ping功能
实现ping功能,就肯定要用到ping命令,那么在Linux下ping命令为: ping [-dfnqrRv][-c<完成次数>][-i<间隔秒数>][-I<网络界面&g ...
- 虚拟机Linux下解决ping时出现 unknown host问题
在虚拟机中使用CentOS6.5时,ping www.baidu.com出现报错信息:“ping: unknown hostwww.baidu.com”,虚拟机和物理机网络连接是NAT方式,物理机访问 ...
- 扔掉360:Linux下无线网卡作WiFi路由器(转薄荷开源网)
这个话题很多人感兴趣,毕竟现在是无线互联时代.手机一族到外面去,首先关心的就是有没有 WiFi.Windows 7 用户可以安装 360 的软件,把笔记本电脑配置成路由器,供手机或其他电脑上网. 在 ...
- 判断内网机器的真实外网IP或域名的方法总结
在内渗透中有时需要在某台WEB服务器中留下后门,可以通过内网IP建立IPC连接,但还需要获知外网IP才能访问Wbshell,在无网关权限的情况下,我总结了有如下方法: nslookup myip.op ...
- centOS7 可以ping通主机不能访问外网
前言: 突然打开自己前不久在虚拟机安装的centOS7系统,发现以前可以来联网突然不能访问外网,在网上看了很多方法,终于解决 问题描述: 连上网,但是ping 不同外网,如ping www.baodu ...
- VM中Linux网络设置(固定ip、连接外网开发环境)
在开发过程中,我们经常需要在linux中进行操作.毕竟服务器的系统大多数都是Linux,所以在dev环境需要配置好一台Linux系统配合开发. 在VMWare Workstation Pro中 ...
- linux下的ping工具--fping
前言: 如果想ping 大量的不连续的地址,有想知道放回结果,在linux系统下有一个非常合适的工具--fping. Fping 官网:http://www.fping.org/ Fpin ...
随机推荐
- suse 12 二进制部署 Kubernetets 1.19.7 - 第03章 - 部署flannel插件
文章目录 1.3.部署flannel网络 1.3.0.下载flannel二进制文件 1.3.1.创建flannel证书和私钥 1.3.2.生成flannel证书和私钥 1.3.3.将pod网段写入et ...
- 6.Flink实时项目之业务数据分流
在上一篇文章中,我们已经获取到了业务数据的输出流,分别是dim层维度数据的输出流,及dwd层事实数据的输出流,接下来我们要做的就是把这些输出流分别再流向对应的数据介质中,dim层流向hbase中,dw ...
- SpringBoot 自定义参数类型转换convert
创建一个配置类.使用 @bean注入到容器中 @Bean public WebMvcConfigurer webMvcConfigurer(){ /** * 实现自定义的addConverter */ ...
- yum配置及使用命令
linux yum 命令 yum( Yellow dog Updater, Modified)是一个在Fedora和RedHat以及SUSE中的Shell前端软件包管理器. 基於RPM包管理,能够从指 ...
- 【基础篇】js对本地文件增删改查--改
前置条件: 1. 本地有安装node,点击传送门 项目目录: 1. msg.json内容 { "data": [ { "id": 1, "name&q ...
- 思迈特软件Smartbi:Excel数据分析常用函数汇总!
多传统行业的数据分析师只要求掌握Excel即可,会SPSS/SAS是加分项.即使在挖掘满街走,Python不如狗的互联网数据分析界,Excel也是不可替代的. Excel是我们工作中经常使用的一种工具 ...
- Python "爬虫"出发前的装备之二数据先行( Requests 模块)
1. 概念 爬虫不是动物,而是一种计算机程序. 这种程序有自己特定的功能,能按照使用者给定的一系列规则自行浏览万维网并获取需要的信息.此类程序被称为 网络爬虫(web crawler) 或 网络蜘蛛( ...
- .NET 5+ 中已过时的功能
从 .NET 5 开始,一些新标记为已过时的 API 使用 ObsoleteAttribute 上的两个新属性. ObsoleteAttribute.DiagnosticId 属性指示编译器使用自定义 ...
- 动态语言运行时(DLR)
前言 为了让C#.Visual Basic等.NET编程语言能具备动态编程语言的特性,.NET 4.0引入了一个"DLR(Dynamic Language Runtime:动态语言运行时)& ...
- 每日一算法之two sum
题目如下:首先准备一个数组,[1,2,8,4,9] 然后输入一个6,找出数组两项之和为6的两个下标. 啥也不想,马上上代码,这个太简单了, static int[] twoSum(int[] num ...