Linuxアプリケーション層は、ネットワークケーブルの挿抜状態をどのように監視するか
方法1:
参照先:https://blog.csdn.net/hbk320/article/details/47300067
linux下のifconfigコマンドは、アプリケーション層でネットワーク線の挿抜状態を監視することができるため、例えば、ネットワーク線が正常に接続されている場合、ifconfig eth 0コマンドを使用すると、印刷された情報にRUNNINGがあり、ネットワーク線を抜いた後、ifconfig eth 0コマンドを使用すると、RUNNINGはなくなります.したがって,Linuxアプリケーション層のモニタリングネットワーク線挿入状態を実現することは,ifconfig関数を自分で書くことに相当する.
次のプログラムの実行例:./a.out eth0
明らかに、以上のプログラムは使用者がポーリングでネットワークの状態を監視しなければならない.
方法2:
参照先:https://blog.csdn.net/muclenerd/article/details/49950257
参照先:https://blog.csdn.net/al86866365/article/details/79066227
参照先:https://blog.csdn.net/gt945/article/details/45315911
cat/sys/class/net/eth0/carrier
carrierが1の場合はconnectを表し、そうでない場合はdisconnectを表します.
通常状態変化がない場合、以下のプログラムは5秒ごとに(select関数によって制御される)サイクルされ、読み取りがモニタされるとread()関数はデータを読み取り、その後のプログラムは各イベントのデータを解析する
参照先:https://blog.csdn.net/hbk320/article/details/47300067
linux下のifconfigコマンドは、アプリケーション層でネットワーク線の挿抜状態を監視することができるため、例えば、ネットワーク線が正常に接続されている場合、ifconfig eth 0コマンドを使用すると、印刷された情報にRUNNINGがあり、ネットワーク線を抜いた後、ifconfig eth 0コマンドを使用すると、RUNNINGはなくなります.したがって,Linuxアプリケーション層のモニタリングネットワーク線挿入状態を実現することは,ifconfig関数を自分で書くことに相当する.
#include
#include
#include
#include
#include
#include
#include
int net_get_gateway(char *gateway)
{
FILE *fp = NULL;
char buf[256];
char cmd[64];
char *tmp;
strcpy(cmd, "ip route");
fp = popen(cmd, "r");
if(NULL == fp)
{
perror("popen error");
return -1;
}
while(fgets(buf, sizeof(buf), fp) != NULL)
{
tmp = buf;
// : default via 192.168.2.1 dev eth0
// default
while(*tmp && isspace(*tmp))
{
++ tmp;
}
if(strncmp(tmp, "default", strlen("default")) == 0)
break;
}
// %*s ,
sscanf(buf, "%*s%*s%s", gateway);
pclose(fp);
return 0;
}
int net_detect(char* net_name)
{
int skfd = 0;
struct ifreq ifr;
struct sockaddr_in *pAddr = NULL;
skfd = socket(AF_INET, SOCK_DGRAM, 0);
if(skfd < 0)
{
printf("Open socket error
");
return -1;
}
// get ifr_flags
strcpy(ifr.ifr_name, net_name);
if(ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)
{
printf("SIOCGIFFLAGS IOCTL error, %s is not valid
", ifr.ifr_name);
close(skfd);
return -1;
}
if(ifr.ifr_flags & IFF_RUNNING)
{
// running up down
// , IFF_UP up
if(ifr.ifr_flags & IFF_UP)
{
printf("%s: is up
", ifr.ifr_name);
}
printf("%s: is running
", ifr.ifr_name);
}
else
{ // not running, down
printf("%s: is down
", ifr.ifr_name);
printf("%s: is NOT running
", ifr.ifr_name);
}
// get HW address
if(ioctl(skfd, SIOCGIFHWADDR, &ifr) < 0)
{
printf("SIOCGIFHWADDR IOCTL error
");
close(skfd);
return -1;
}
printf("%s: HW_ADDR: %02X:%02X:%02X:%02X:%02X:%02X
",
net_name,
(unsigned char)ifr.ifr_hwaddr.sa_data[0],
(unsigned char)ifr.ifr_hwaddr.sa_data[1],
(unsigned char)ifr.ifr_hwaddr.sa_data[2],
(unsigned char)ifr.ifr_hwaddr.sa_data[3],
(unsigned char)ifr.ifr_hwaddr.sa_data[4],
(unsigned char)ifr.ifr_hwaddr.sa_data[5]);
// get IP address
if(ioctl(skfd, SIOCGIFADDR, &ifr) < 0)
{
printf("SIOCGIFADDR IOCTL error
");
close(skfd);
return -1;
}
pAddr = (struct sockaddr_in *)&(ifr.ifr_addr);
printf("%s: IP_ADDR: %s
", net_name, inet_ntoa(pAddr->sin_addr));
// get broadcast address
if(ioctl(skfd, SIOCGIFBRDADDR, &ifr) < 0)
{
printf("SIOCGIFBRDADDR IOCTL error
");
close(skfd);
return -1;
}
pAddr = (struct sockaddr_in *)&(ifr.ifr_addr);
printf("%s: BROADCAST: %s
", net_name, inet_ntoa(pAddr->sin_addr));
// get netmask address
if(ioctl(skfd, SIOCGIFNETMASK, &ifr) < 0)
{
printf("SIOCGIFNETMASK IOCTL error
");
close(skfd);
return -1;
}
pAddr = (struct sockaddr_in *)&(ifr.ifr_addr);
printf("%s: NET_MASK: %s
", net_name, inet_ntoa(pAddr->sin_addr));
// get gateway address
char gateway[16] = {0};
net_get_gateway(gateway);
printf("%s: GATEWAY: %s
", net_name, gateway);
close(skfd);
return 0;
}
int main(int argc, char *argv[])
{
char net_name[8] = {0};
if(argc != 2)
{
printf("arg error
");
return -1;
}
memcpy(net_name, argv[1], strlen(argv[1]));
return net_detect(net_name);
}
次のプログラムの実行例:./a.out eth0
明らかに、以上のプログラムは使用者がポーリングでネットワークの状態を監視しなければならない.
方法2:
参照先:https://blog.csdn.net/muclenerd/article/details/49950257
参照先:https://blog.csdn.net/al86866365/article/details/79066227
参照先:https://blog.csdn.net/gt945/article/details/45315911
cat/sys/class/net/eth0/carrier
carrierが1の場合はconnectを表し、そうでない場合はdisconnectを表します.
通常状態変化がない場合、以下のプログラムは5秒ごとに(select関数によって制御される)サイクルされ、読み取りがモニタされるとread()関数はデータを読み取り、その後のプログラムは各イベントのデータを解析する
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#include
#define BUFLEN 20480
int main(int argc, char *argv[])
{
int fd, retval;
char buf[BUFLEN] = {0};
int len = BUFLEN;
struct sockaddr_nl addr;
struct nlmsghdr *nh;
struct rtattr *attr;
fd_set rd_set;
struct timeval timeout;
int select_r;
// 1. NetLink Socket
// AF_NETLINK PF_NETLINK, Linux , , netlink
// SOCK_RAW SOCK_DGRAM
// netlink , NETLINK_ROUTE “ ”
// fd ( eth0 )
fd = socket(AF_NETLINK, SOCK_RAW, NETLINK_ROUTE);
setsockopt(fd, SOL_SOCKET, SO_RCVBUF, &len, sizeof(len));
// 2. Socket
memset(&addr, 0, sizeof(addr));
addr.nl_family = AF_NETLINK;
// + IPV4
addr.nl_groups = RTMGRP_LINK | RTMGRP_IPV4_IFADDR;
// bind() netlink socket netlink socket
bind(fd, (struct sockaddr*)&addr, sizeof(addr));
while(1)
{
// ,
FD_ZERO(&rd_set);
//
FD_SET(fd, &rd_set);
timeout.tv_sec = 5;
timeout.tv_usec = 0;
// read() , select()
// select() ——
// select() fd , select_r 0; fd , 0
select_r = select(fd + 1, &rd_set, NULL, NULL, &timeout);
if(select_r < 0)
{
printf("select() return error
");
}
else if(select_r > 0)
{
if(FD_ISSET(fd, &rd_set))
{
retval = read(fd, buf, BUFLEN);
for(nh = (struct nlmsghdr *)buf; NLMSG_OK(nh, retval); nh = NLMSG_NEXT(nh, retval))
{
if(nh->nlmsg_type == NLMSG_DONE)
break;
else if(nh->nlmsg_type == NLMSG_ERROR)
return;
else if(nh->nlmsg_type == RTM_NEWLINK)
{
struct ifinfomsg *ifinfo;
ifinfo = NLMSG_DATA(nh);
printf("NEWLINK: %s", (ifinfo->ifi_flags & IFF_LOWER_UP) ? "up" : "down");
attr = (struct rtattr*)(((char*)nh) + NLMSG_SPACE(sizeof(*ifinfo)));
len = nh->nlmsg_len - NLMSG_SPACE(sizeof(*ifinfo));
for(; RTA_OK(attr, len); attr = RTA_NEXT(attr, len))
{
if(attr->rta_type == IFLA_IFNAME)
{
printf(" %s", (char*)RTA_DATA(attr));
break;
}
}
printf("
");
}
else if(nh->nlmsg_type == RTM_NEWADDR || nh->nlmsg_type == RTM_DELADDR)
{
struct ifaddrmsg *ifaddr;
ifaddr = NLMSG_DATA(nh);
printf("%s:", (nh->nlmsg_type==RTM_NEWADDR)?"NEWADDR":"DELADDR");
attr = (struct rtattr*)(((char*)nh) + NLMSG_SPACE(sizeof(*ifaddr)));
len = nh->nlmsg_len - NLMSG_SPACE(sizeof(*ifaddr));
for(; RTA_OK(attr, len); attr = RTA_NEXT(attr, len))
{
if(attr->rta_type == IFA_ADDRESS)
{
char tmp[32] = {0};
inet_ntop(ifaddr->ifa_family, RTA_DATA(attr), tmp, sizeof(tmp));
printf(" %s", tmp);
}
if(attr->rta_type == IFA_LABEL)
{
printf(" %s", (char*)RTA_DATA(attr));
break;
}
}
printf("
");
}
}
}
}
}
close(fd);
return 0;
}