zoukankan      html  css  js  c++  java
  • 网络编程中一些小函数,getifaddrs()等

    #include <stdio.h>
    #include <stdlib.h>
    #include <sys/ioctl.h>
    #include <sys/types.h>
    #include <sys/socket.h>
    #include <unistd.h>
    #include <string.h>
    
    #include <net/if.h>
    #include <net/if_arp.h>
    #include <arpa/inet.h>
    #include <errno.h>
    
    
    typedef long LONG;
    typedef char CHAR;
    #define CONST const
    
    #ifndef  SUCCESS
    #define  SUCCESS             0
    #endif
    
    #ifndef  FAIL
    #define  FAIL               -1
    #endif
    
    
    
    LONG GetMac(CONST CHAR *pcIfName, CHAR *pcMac)
    { 
        if (NULL == pcIfName || NULL == pcMac)
        {
            printf("NULL == pcIfName || NULL == pcMac\n");
            return FAIL;
        }
        
        LONG lFd = 0, lRet = FAIL; 
        struct ifreq ifr;
        memset(&ifr, 0, sizeof(ifr)); 
        strcpy(ifr.ifr_name, pcIfName); 
        
        lFd = socket(AF_INET, SOCK_STREAM, 0); 
        if(lFd < 0)
        { 
            printf("socket fail\n");
            return FAIL; 
        } 
    
        //lRet = ioctl(lFd, SIOCGIFHWADDR, &ifr, sizeof(ifr)); 
    	lRet = ioctl(lFd, SIOCGIFHWADDR, &ifr); 
        if(0 == lRet) 
        { 
            memcpy(pcMac, ifr.ifr_hwaddr.sa_data, 6);
    		printf("\nifr.ifr_hwaddr.sa_data is %s   \n",ifr.ifr_hwaddr.sa_data);
            close(lFd); 
            return SUCCESS;
        }   
        else   
        { 
            printf("ioctl fail\n");
            close(lFd);
            return FAIL;
        }
    }
    
    LONG GetIp(CONST CHAR *pcIfName, CHAR *pcIp)
    { 
        if (NULL == pcIfName || NULL == pcIp)
        {
            printf("NULL == pcIfName || NULL == pcIp\n");
            return FAIL;
        }
        
        LONG lFd = 0, lRet = FAIL; 
        struct ifreq ifr;
        memset(&ifr, 0, sizeof(ifr)); 
        strcpy(ifr.ifr_name, pcIfName); 
        
        lFd = socket(AF_INET, SOCK_STREAM, 0); 
        if(lFd < 0)
        { 
            printf("socket fail\n");
            return FAIL; 
        } 
    
        lRet = ioctl(lFd, SIOCGIFADDR, &ifr); 
        if(0 == lRet) 
        { 
            strncpy(pcIp,inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr),16);
            close(lFd); 
            return SUCCESS;
        }   
        else   
        { 
            printf("ioctl fail\n");
            close(lFd);
            return FAIL;
        }
    }
    
    
    int main()
    {
        LONG lRet = FAIL;
        CHAR szMac[6] = {0};
    	CHAR szIp[16] = {0};
    	
        CHAR szID[21] = {0};
    	int i=0;
    	int ulLen = 0;	
        
        lRet = GetMac("eth0", szMac);
    	
    	for(i = 0; i < sizeof(szMac); i++)
        {
            //sprintf(szID + strlen((const char*)szID), "%02X", szMac[i]);
    		//ulLen = snprintf(szID, 1024, "%02X", szMac[i]);
    		//ulLen +=snprintf((szID + ulLen), 1024, "%02X", szMac[i]);
    		printf("%0x,",szMac[i]);
        }
    	printf("\nlRet is %d,mac is %s\n",lRet,szID);
    	
    	lRet = GetIp("eth0", szIp);
    	
    	printf("lRet is %d,szIp is %s\n",lRet,szIp);
    
    	return 0;
    }
    
    

    getifaddrs()和struct ifaddrs的使用,获取本机IP 

    http://canlynet.iteye.com/blog/1440054

    ifaddrs结构体定义如下:

    struct ifaddrs 
    { 
        struct ifaddrs  *ifa_next;    /* Next item in list */ 
        char            *ifa_name;    /* Name of interface */ 
        unsigned int     ifa_flags;   /* Flags from SIOCGIFFLAGS */ 
        struct sockaddr *ifa_addr;    /* Address of interface */ 
        struct sockaddr *ifa_netmask; /* Netmask of interface */ 
        union 
        { 
            struct sockaddr *ifu_broadaddr; /* Broadcast address of interface */ 
            struct sockaddr *ifu_dstaddr; /* Point-to-point destination address */ 
        } ifa_ifu; 
        #define              ifa_broadaddr ifa_ifu.ifu_broadaddr 
        #define              ifa_dstaddr   ifa_ifu.ifu_dstaddr 
        void            *ifa_data;    /* Address-specific data */ 
    }; 
    

    ifa_next指向链表的下一个成员;ifa_name是接口名称,以0结 尾的字符串,比如eth0,lo;ifa_flags是接口的标识位(比如当IFF_BROADCAST或IFF_POINTOPOINT设置到此标识位 时,影响联合体变量ifu_broadaddr存储广播地址或ifu_dstaddr记录点对点地址);ifa_netmask存储该接口的子网掩码;结 构体变量存储广播地址或点对点地址(见括弧介绍ifa_flags);ifa_data存储了该接口协议族的特殊信息,它通常是NULL(一般不关注 他)。

        函数getifaddrs(int getifaddrs (struct ifaddrs **__ifap))获取本地网络接口信息,将之存储于链表中,链表头结点指针存储于__ifap中带回,函数执行成功返回0,失败返回-1,且为errno赋值。
        很显然,函数getifaddrs用于获取本机接口信息,比如最典型的获取本机IP地址。

    /* Standard interface flags. */
    enum
      {
        IFF_UP = 0x1,       /* Interface is up.  */
    # define IFF_UP IFF_UP
        IFF_BROADCAST = 0x2,    /* Broadcast address valid.  */
    # define IFF_BROADCAST  IFF_BROADCAST
        IFF_DEBUG = 0x4,        /* Turn on debugging.  */
    # define IFF_DEBUG  IFF_DEBUG
        IFF_LOOPBACK = 0x8,     /* Is a loopback net.  */
    # define IFF_LOOPBACK   IFF_LOOPBACK
        IFF_POINTOPOINT = 0x10, /* Interface is point-to-point link.  */
    # define IFF_POINTOPOINT IFF_POINTOPOINT
        IFF_NOTRAILERS = 0x20,  /* Avoid use of trailers.  */
    # define IFF_NOTRAILERS IFF_NOTRAILERS
        IFF_RUNNING = 0x40,     /* Resources allocated.  */
    # define IFF_RUNNING    IFF_RUNNING
        IFF_NOARP = 0x80,       /* No address resolution protocol.  */
    # define IFF_NOARP  IFF_NOARP
        IFF_PROMISC = 0x100,    /* Receive all packets.  */
    # define IFF_PROMISC    IFF_PROMISC

        /* Not supported */
        IFF_ALLMULTI = 0x200,   /* Receive all multicast packets.  */
    # define IFF_ALLMULTI   IFF_ALLMULTI

        IFF_MASTER = 0x400,     /* Master of a load balancer.  */
    # define IFF_MASTER IFF_MASTER
        IFF_SLAVE = 0x800,      /* Slave of a load balancer.  */
    # define IFF_SLAVE  IFF_SLAVE

        IFF_MULTICAST = 0x1000, /* Supports multicast.  */
    # define IFF_MULTICAST  IFF_MULTICAST

        IFF_PORTSEL = 0x2000,   /* Can set media type.  */
    # define IFF_PORTSEL    IFF_PORTSEL
        IFF_AUTOMEDIA = 0x4000, /* Auto media select active.  */
    # define IFF_AUTOMEDIA  IFF_AUTOMEDIA
        IFF_DYNAMIC = 0x8000    /* Dialup device with changing addresses.  */
    # define IFF_DYNAMIC    IFF_DYNAMIC
      };

    网络设备 的 套接字(socket) 接口

    http://blog.sina.com.cn/s/blog_4bb620d50100083u.html

    #include <sys/ioctl.h>
    #include <net/if.h>

    描述 (DESCRIPTION)

    本手册 描述 用于 配置 网络设备 的 套接字(socket) 接口.

    Linux 支持 一些 配置 网络设备 的 标准 ioctl. 他们用于任意的套接字 描述符, 而 无须 了解 其 类型 或 系列. 他们 传递一个 ifreq 结构:

    struct ifreq
    {
    char ifr_name[IFNAMSIZ]; /* Interface name */ union { struct sockaddr ifr_addr; struct sockaddr ifr_dstaddr; struct sockaddr ifr_broadaddr; struct sockaddr ifr_netmask; struct sockaddr ifr_hwaddr; short ifr_flags; int ifr_ifindex; int ifr_metric; int ifr_mtu; struct ifmap ifr_map; char ifr_slave[IFNAMSIZ]; char ifr_newname[IFNAMSIZ]; char * ifr_data; }; }
    struct ifconf { int ifc_len; /* size of buffer */
    union {
    char * ifc_buf; /* buffer ddress */ struct ifreq *ifc_req; /* array of structures */
    }; };
    一般说来, ioctl 通过 把 ifr_name 设置为 接口 的 名字 来指定 将要 操作 的 设备. 结构的 其他成员 可以 分享 内存.

    IOCTLS

    如果 某个 ioctl 标记为 特权操作, 那么 操作时 需要 有效uid 为 0, 或者 拥有 CAP_NET_ADMIN 能力. 否则 将 返回 EPERM .

    SIOCGIFNAME

          给定 ifr_ifindex, 返回 ifr_name 中 的 接口名字. 这是唯一 返回 ifr_name 内容 的 ioctl.

    SIOCGIFINDEX
    把 接口 的 索引 存入 ifr_ifindex.
    SIOCGIFFLAGS, SIOCSIFFLAGS
    读取 或 设置 设备的 活动标志字. ifr_flags 包含下列值的屏蔽位:
    设备标志
    IFF_UP 接口正在运行.
    IFF_BROADCAST 有效的广播地址集.
    IFF_DEBUG 内部调试标志.
    IFF_LOOPBACK 这是自环接口.
    IFF_POINTOPOINT 这是点到点的链路接口.
    IFF_RUNNING 资源已分配.
    IFF_NOARP 无arp协议, 没有设置第二层目的地址.
    IFF_PROMISC 接口为杂凑(promiscuous)模式.
    IFF_NOTRAILERS 避免使用trailer .
    IFF_ALLMULTI 接收所有组播(multicast)报文.
    IFF_MASTER 主负载平衡群(bundle).
    IFF_SLAVE 从负载平衡群(bundle).
    IFF_MULTICAST 支持组播(multicast).
    IFF_PORTSEL 可以通过ifmap选择介质(media)类型.
    IFF_AUTOMEDIA 自动选择介质.
    IFF_DYNAMIC 接口关闭时丢弃地址.

    设置 活动标志字 是 特权操作, 但是 任何进程 都可以读取标志字.

    SIOCGIFMETRIC, SIOCSIFMETRIC
    使用 ifr_metric 读取 或 设置 设备的 metric 值. 该功能目前 还没有 实现. 读取操作 使 ifr_metric 置 0, 而设置操作则 返回 EOPNOTSUPP.
    SIOCGIFMTU, SIOCSIFMTU
    使用 ifr_mtu 读取 或 设置 设备的 MTU(最大传输单元). 设置 MTU 是 特权操作. 过小的 MTU 可能 导致 内核 崩溃.
    SIOCGIFHWADDR, SIOCSIFHWADDR
    使用 ifr_hwaddr 读取 或 设置 设备的 硬件地址. 设置硬件地址 是 特权操作.
    SIOCSIFHWBROADCAST
    使用 ifr_hwaddr 读取 或 设置 设备的 硬件广播地址. 这是个特权操作.
    SIOCGIFMAP, SIOCSIFMAP
    使用 ifr_map 读取 或 设置 接口的 硬件参数. 设置这个参数是 特权操作.
    struct ifmap 
    {
    unsigned long mem_start;
    unsigned long mem_end;
    unsigned short base_addr;
    unsigned char irq;
    unsigned char dma;
    unsigned char port;
    };
    对 ifmap 结构 的 解释 取决于 设备驱动程序 和 体系结构.
    
    SIOCADDMULTI, SIOCDELMULTI
    使用 ifr_hwaddr 在 设备的 链路层 组播过滤器 (multicase filter) 中 添加 或 删除 地址. 这些是 特权操作. 参看 packet(7).
    SIOCGIFTXQLEN, SIOCSIFTXQLEN
    使用 ifr_qlen 读取 或 设置 设备的 传输队列长度. 设置传输队列长度 是 特权操作.
    SIOCSIFNAME
    ifr_ifindex 中 指定的 接口名字 改成 ifr_newname. 这是个 特权操作.
    SIOCGIFCONF
    返回 接口地址(传输层) 列表. 出于 兼容性, 目前 只代表 AF_INET 地址. 用户 传送 一个 ifconf 结构 作为 ioctl 的 参数. 其中 ifc_req 包含 一个 指针 指向 ifreq 结构数组, 他的长度以字节 为单位 存放在 ifc_len 中. 内核 用 所有 当前的 L3(第三层?) 接口地址 填充 ifreqs, 这些 接口 正在 运行: ifr_name 存放 接口名字 (eth0:1等), ifr_addr 存放地址. 内核 在 ifc_len 中 返回 实际长度; 如果 他 等于初始长度, 表示溢出了, 用户 应该 换一个 大些的 缓冲区 重试 一下. 没有 发生错误时 ioctl 返回 0, 否则 返回 -1, 溢出 不算 错误.

    大多数 协议 使用 自己的 ioctl 配置 协议 特定的 接口 操作. 具体情况参看 协议的 帮助手册. 要配置 IP 地址 可以 参看 ip(7).

    另外, 某些 设备 有 专用的 ioctl, 这里 不做 叙述.

    注意 (NOTE)

    严格说来 SIOCGIFCONF 是 专门 针对 IP 的, 它 属于 ip(7).

    注意 (NOTE)

    可以 通过 /proc/net/dev 看到 没有 地址 或 没有 IFF_RUNNING 标志 的 接口名字.

    /* Interface request structure used for socket ioctl's.  All interface
       ioctl's must have parameter definitions which begin with ifr_name.
       The remainder may be interface specific.  */

    struct ifreq
      {
    # define IFHWADDRLEN    6
    # define IFNAMSIZ   IF_NAMESIZE
        union
          {
        char ifrn_name[IFNAMSIZ];   /* Interface name, e.g. "en0".  */
          } ifr_ifrn;

        union
          {
        struct sockaddr ifru_addr;
        struct sockaddr ifru_dstaddr;
        struct sockaddr ifru_broadaddr;
        struct sockaddr ifru_netmask;
        struct sockaddr ifru_hwaddr;
        short int ifru_flags;
        int ifru_ivalue;
        int ifru_mtu;
        struct ifmap ifru_map;
        char ifru_slave[IFNAMSIZ];  /* Just fits the size */
        char ifru_newname[IFNAMSIZ];
        __caddr_t ifru_data;
          } ifet_ifru;
      };
    # define ifr_name   ifr_ifrn.ifrn_name  /* interface name   */
    # define ifr_hwaddr ifr_ifru.ifru_hwaddr    /* MAC address      */
    # define ifr_addr   ifr_ifru.ifru_addr  /* address      */
    # define ifr_dstaddr    ifr_ifru.ifru_dstaddr   /* other end of p-p lnk */
    # define ifr_broadaddr  ifr_ifru.ifru_broadaddr /* broadcast address    */
    # define ifr_netmask    ifr_ifru.ifru_netmask   /* interface net mask   */
    # define ifr_flags  ifr_ifru.ifru_flags /* flags        */
    # define ifr_metric ifr_ifru.ifru_ivalue    /* metric       */
    # define ifr_mtu    ifr_ifru.ifru_mtu   /* mtu          */
    # define ifr_map    ifr_ifru.ifru_map   /* device map       */
    # define ifr_slave  ifr_ifru.ifru_slave /* slave device     */
    # define ifr_data   ifr_ifru.ifru_data  /* for use by interface */
    # define ifr_ifindex    ifr_ifru.ifru_ivalue    /* interface index      */
    # define ifr_bandwidth  ifr_ifru.ifru_ivalue    /* link bandwidth   */
    # define ifr_qlen   ifr_ifru.ifru_ivalue    /* queue length     */
    # define ifr_newname    ifr_ifru.ifru_newname   /* New name     */
    # define _IOT_ifreq _IOT(_IOTS(char),IFNAMSIZ,_IOTS(char),16,0,0)
    # define _IOT_ifreq_short _IOT(_IOTS(char),IFNAMSIZ,_IOTS(short),1,0,0)
    # define _IOT_ifreq_int _IOT(_IOTS(char),IFNAMSIZ,_IOTS(int),1,0,0)

  • 相关阅读:
    【转】Exchange Server 的防火墙开放端口
    【转】AD常用端口
    centos6安装python3
    CMD下的netstat命令
    CMD定时倒数
    【转】netstat 的10个基本用法
    不联网如何PING通WIN主机和VMWARE(懵懂版,不含原理)
    【转载】Putty出现 Network error:Software caused connection abort
    MFC Unicode 字符集下格式转换
    MFC嵌套OpenCV窗口并显示图片
  • 原文地址:https://www.cnblogs.com/jingzhishen/p/3026225.html
Copyright © 2011-2022 走看看