zoukankan      html  css  js  c++  java
  • Lniux网络接口(ioctl)

    概述

    iotcl函数

    在示例程序中多次使用到了ioctl函数,使用这个函数直接获取数据。ioctl用户函数实际上就是为驱动为用户程序提供一个get/set接口,其间是内核做一次转换,内核将驱动程序和用户程序连接起来,可以参考文章(https://blog.csdn.net/qq_19923217/article/details/82698787)中的图示很容易看懂。
    函数原型为int ioctl(int fd, int cmd, ...) ;其中cmd在指的就是接口请求命令,在接下来一小节有介绍。

    接口请求命令

    SIOCGIFCONF请求为每个已经被配置的接口返回其名字以及一个套接字地址结构,也有许多其他的类似接口请求(如下表),这些请求的获取(get)版本(SIOCGxxx)通常由netstat程序发出,设置(set)版本(SIOCSxxx)通常由ifconfig程序发出。任何用户都可以获取接口信息,设置接口信息却要求具备超级用户权限。以下是一些通用接口请求,许多实现中都加入了其他的请求。

    程序示例

    本程序主要展示ioctl的使用方法,使用ioctl获取网络设备的数据。
    程序参考以下两篇文章:
    https://blog.csdn.net/baicong9439/article/details/101089278
    https://blog.csdn.net/q_l_s/article/details/52716730

    
    #include<stdlib.h>  
    #include<stdio.h>  
    #include<unistd.h>  
    #include<net/if.h>  
    #include<net/if_arp.h>  
    #include<arpa/inet.h>  
    #include<sys/ioctl.h>  
    #include<errno.h>  
       
    #define ETH_NAME  "eth0"  
    #define IFNAMSIZ  32
    
    static void get_ifconfig(int sock_fd)  
    {
        int i=0;
        struct ifconf _ifconf;
        unsigned char buf[512];
        struct ifreq *_ifreq;
        //初始化ifconf
        _ifconf.ifc_len = 512;
        _ifconf.ifc_buf = buf;
    
        ioctl(sock_fd, SIOCGIFCONF, &_ifconf); //获取所有接口信息
    
        /* 接下来一个一个的获取IP地址 */
        _ifreq = (struct _ifreq*)buf;
    	
        /* 一个网络设备可能会有多张网卡多个网络接口 */
        for (i = (_ifconf.ifc_len/sizeof (struct _ifreq)); i > 0; i --)
        {
            /* for ipv4 */
            if(_ifreq->ifr_addr.sa_family == AF_INET)
    	{ 
    	        printf("name = [%s]/n" , _ifreq->ifr_name);
    	        printf("local addr = [%s]/n" , inet_ntoa(((struct sockaddr_in*)&(_ifreq->ifr_addr))->sin_addr));
    
    			_ifreq ++;
            }
        }
    	
        return ;
    }
    
    static void get_network_interface_params(int sock_fd, char *net_interface, int cmd)  
    {  
    	strncpy(ifr.ifr_name, net_interface, IFNAMSIZ);  
    	ifr.ifr_name[IFNAMSIZ - 1] = 0;  
    	if(ioctl(sock_fd, cmd, &ifr) == 0)  
    	{  
    		memcpy(&sin,&ifr.ifr_addr,sizeof(sin));  
    		printf("eth0: %s
    ",inet_ntoa(sin.sin_addr));  
    	}  
    }  
    
    int main()  
    {  
            int sockfd;  
    	struct sockaddr_in  sin;  
    	struct sockaddr_in  netmask;  
    	struct sockaddr_in  broad;  
    	struct ifreq ifr;  
    	unsigned char had[6];  
    
    	
    	sockfd = socket(AF_INET, SOCK_DGRAM, 0);  
    	if(sockfd == -1)  
    	{  
    		perror("create socket failed !");  
    		return -1;  
    	}  
    	
    	/* get a specific network interface info */
    	/* get_local_ip */
    	get_network_interface_params(sockfd, ETH_NAME, SIOCGIFADDR);
    	/* get_mac_addr */
    	get_network_interface_params(sockfd, ETH_NAME, SIOCGIFHWADDR);
    	/* get_netmask_addr */
    	get_network_interface_params(sockfd, ETH_NAME, SIOCGIFNETMASK);
    	/* get_broad_addr */  
    	get_network_interface_params(sockfd, ETH_NAME, SIOCGIFBRDADDR);
    
    	/* get all network interface info */
    	get_ifconfig(sockfd);
    	
    	return 0;  
    }  
    
    
    

    其中关于ifreq和ifconf的部分结构以下给出作为参考,事实上这些结构内容更多一些,这里只作为示例。如果对ifconf结构与ifreq结构的联合使用不太清楚,在文章(http://www.360doc.com/content/17/0510/17/8335678_652752795.shtml)的图示中可以看的很明白。

    
    struct ifconf
    {
    	long ifc_len;
    	union
    	{
    	    char  *ifcu_buf;
    	    struct ifreq *ifcu_req;
    	}ifc_ifcu;
    };
    
    #define ifc_buf ifc_ifcu.ifcu_buf
    #define ifc_req ifc_ifcu.ifcu_req
    
    
    struct ifreq
    {
            char ifr_name[IFNAMSIZ];
    	union
    	{
    	    struct  sockaddr  ifru_addr;
    	    struct  sockaddr  ifru_dstaddr;
    	    struct  sockaddr  ifru_broadaddr;
    	    struct  sockaddr  ifru_netmask;
    	    struct  sockaddr  ifru_hwaddr;
    	    short   ifru_flags;
    	    int     ifru_metric;
    	    char    *ifru_data;
    	}ifr_ifru;
    };
    
    #define ifr_addr        ifr_ifru.ifru_addr
    #define ifr_broadaddr   ifr_ifru.ifru_broadaddr
    #define ifr_hwaddr      ifr_ifru.ifru_hwaddr
    
    

    补充知识

    以下都参考自(https://blog.csdn.net/will130/article/details/53326740)

    sockaddr和sockaddr_in详解

    sockaddr_in可以强制转换成sockaddr结构,sockaddr结构多用于bing,connect,recvfrom,sendto等操作
    struct sockaddr_in mysock;
    (struct sockaddr *)&mysock

    网络字节序与主机字节序转换

    在数据传输过程中使用网络字节序,在数据表示的时候多使用主机字节序字符串

    编号 函数名称 操作对象 转换
    1 htons() 端口号 主机字节序->网络字节序
    2 inet_addr() IP字符串 主机字节序->网络字节序
    3 inet_ntoa() sin_addr结构 网络字节序->主机字节序

    以上

  • 相关阅读:
    微软经典项目实例
    Extjs在vs中使用及弹出对话框的介绍
    微软企业库5.0学习笔记(七)
    微软企业库5.0学习笔记(八)
    微软企业库5.0学习笔记(十)
    .NET 4 并行(多核)编程系列之五
    NET 应用架构指导 V2[12]
    .NET 4 并行(多核)编程系列之四
    .NET 4 并行(多核)编程系列之三
    微软企业库5.0学习笔记(十二)
  • 原文地址:https://www.cnblogs.com/y-c-y/p/14719247.html
Copyright © 2011-2022 走看看