Linuxアプリケーション層は、ネットワークケーブルの挿抜状態をどのように監視するか


方法1:
参照先: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; }