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 ...
随机推荐
- 关于mybatis,需要掌握的基础
目录 ❀ 总结 mybatis,需要掌握的基础如下: 1.了解ORM 思想.ORM思想的作用.映射配置的两种方式 2.MyBatis开发流程(基本使用) 3.日志框架 4.了解mybatis生命周期并 ...
- String类型转int类型方法
System.out.println( "Integer.parseInt(\"5\") =" + Integer.parseInt("5" ...
- iOS动态库和静态库的运用
概念认识 什么是库 库是共享程序代码的方式,库从本质上来说是一种可执行代码的二进制格式,可以被载入内存中执行.在开发过程中,一些核心技术或者常用框架,出于安全性和稳定性的考虑,不想被外界知道,所以会把 ...
- 60天shell脚本计划-12/12-渐入佳境
--作者:飞翔的小胖猪 --创建时间:2021年3月23日 --修改时间:2021年3月27日 说明 每日上传更新一个shell脚本,周期为60天.如有需求的读者可根据自己实际情况选用合适的脚本,也可 ...
- 通过对比语法差异,让会JAVA的你快速学会Kotlin的开源宝藏项目
今天有个小伙伴来问TJ君,说自己JAVA用的贼溜,想再学习下Kotlin,问TJ君上手难不难? 怎么说呢?其实TJ君一直觉得语言这方面,是触类旁通.一通百通的,既然JAVA已经贼溜了,想必学其他的语言 ...
- Qt:QNetworkRequest
0.说明 QNetworkRequest类代表被QNetworkAccessManager发送的请求. QNetworkReuqest是网络访问API的一部分,在其内部保留了在网络上发送一个reque ...
- Linux CentOS 7.X-关机、重启命令
一.命令操作 1.退出命令 退出登陆命令:logout: 2.关闭命令 立即关机:shutdown -h now(root用户) halt poweroff 延时关机:shutdown -h m ...
- 搞懂MySQL(各种)索引类型及其区别
索引的概念介绍: 1.聚集索引 聚集索引:指索引项的排序方式和表中数据记录排序方式一致的索引 也就是说聚集索引的顺序就是数据的物理存储顺序.它会根据聚集索引键的顺序来存储表中的数据,即对表的数据按索 ...
- 矩池云利用ipykernel为JupyterLab添加kernel以及展示出来
source activate myconda pip install ipykernel python -m ipykernel install --user --name myconda --di ...
- SQL从零到迅速精通【基本语句】
1.使用T-SQL语句创建数据表authors,输入语句如下. CREATE TABLE authors { auth_id int PRIMARY KEY,--数据表主键 auth_name VAR ...