#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <sys/stat.h>
#include <ctype.h>
#include <fcntl.h>
#include <iostream>
#include <string>
template<class T>
class SingleInstance {
public:
static inline T instance() {
static T obj;
return obj;
}
private:
SingleInstance() = default;
~SingleInstance() = default;
};
struct NetInfo {
double send_traffic;
double recv_traffic;
double send_traffic_rate;
double recv_traffic_rate;
};
enum class NetErrCode {
NoError,
ETH_INVALID,
NET_DEV_FILE_OPEN_FAILED,
NET_DEV_FILE_READ_FAILED,
ETH_LACK_FROM_NET_DEV_FILE
};
class NetUtility {
public:
NetErrCode get_net_traffic(const char *eth, NetInfo &net_info) {
if (false == check_eth(eth)) {
return NetErrCode::ETH_INVALID;
}
int fd = open(NET_DEV_FILE, O_RDONLY | O_EXCL);
if (fd < 0) {
return NetErrCode::NET_DEV_FILE_OPEN_FAILED;
}
char buf[BUF_SIZE] = "";
if (read(fd, buf, sizeof(buf) - 1) <= 0) {
close(fd);
return NetErrCode::NET_DEV_FILE_READ_FAILED;
}
close(fd);
char *pDev = strstr(buf, eth);
if (nullptr == pDev) {
return NetErrCode::ETH_LACK_FROM_NET_DEV_FILE;
}
int count = 0;
char *p = strtok(pDev, NET_DEV_INFO_SEPARATION);
for (;p != nullptr;p = strtok(nullptr, NET_DEV_INFO_SEPARATION)) {
if (++count == 2) {
net_info.recv_traffic = atof(p);
}
else if (10 == count) {
net_info.send_traffic = atof(p);
break;
}
}
net_info.send_traffic /= M_SIZE;
net_info.recv_traffic /= M_SIZE;
return NetErrCode::NoError;
}
void get_net_traffic_rate(const char *eth, NetInfo &net_info) {
get_net_traffic(eth, net_info);
double recv_tmp = net_info.recv_traffic;
double send_tmp = net_info.send_traffic;
sleep(1);
get_net_traffic(eth, net_info);
net_info.recv_traffic_rate = net_info.recv_traffic - recv_tmp;
net_info.send_traffic_rate = net_info.send_traffic - send_tmp;
}
bool check_eth(const char *eth) {
if (0 == strlen(eth) || strlen(eth) > 25) {
return false;
}
for (int i = 0;eth[i];i++) {
if (!isalpha(eth[i]) && !isdigit(eth[i])) {
return false;
}
}
return true;
}
private:
constexpr static const char * const NET_DEV_FILE = "/proc/net/dev";
constexpr static const char * const NET_DEV_INFO_SEPARATION = " \t\r\n";
constexpr static size_t BUF_SIZE = 2 * 1024;
constexpr static size_t M_SIZE = 1024 * 1024;
};
#define G_NET_UTILITY SingleInstance<NetUtility>::instance()
int main() {
NetInfo netInfo = {0};
NetErrCode retcode = G_NET_UTILITY.get_net_traffic("enp2s0", netInfo);
if (NetErrCode::NoError == retcode) {
std::cout << "send traffic = " << netInfo.send_traffic << "M" << std::endl;
std::cout << "recv traffic = " << netInfo.recv_traffic << "M" << std::endl;
G_NET_UTILITY.get_net_traffic_rate("enp2s0", netInfo);
std::cout << "send traffic rate = " << netInfo.send_traffic_rate << "M/s" << std::endl;
std::cout << "recv traffic rate = " << netInfo.recv_traffic_rate << "M/s" << std::endl;
}
else {
//std::cerr << "error code = " << retcode;
}
return 0;
}