一、通过流套接字去底层获取:
1、创建流套接字;
2、使用ioctl()和获取匹配指定的宏获取 指定的信息;
3、取出信息进行存储 和 使用。
int netGetMac(char *pinterface, unsigned char *pMac)
{
struct ifreq ifreq;
int sockfd = 0;
unsigned char mac[6] = {};
//创建与底层交互的套接字
if((sockfd = socket(ASF_INET, SOCK_STREAM, 0)) < 0)
{
perror("netGetMac socket");
return -1;
}
strcpy(ifreq.ifr_name, pinterface);
通过ioctl()获取指定信息
if(icotl(sockfd, SIOCGIFHWADDR, &ifreq) < 0)
{
perror("netGetMac icotl");
close(sockfd);
return -1;
}
//存储信息
memcpy(mac, ifreq.ifr_hwaddr.sa_data, 6);
printf("MAC:02x-02x-02x-02x-02x-02x\n");
if(NULL != pMac)
{
memcpy(pMac, mac, 6);
}
close(sockfd);
return 0;
}
int netGetIp(char *interface, unsigned int *ip)
{
int sockfd = -1;
struct ifreq ifr;
if((NULL == interface) || ('\0' == interface))
{
printf("get ip :interface == NULL\r\n");
return -1;
}
memset(&ifr, 0, sizeof(ifr));
strncpy(ifr.ifr_name, interface, IFNAMSIZ);
//创建与底层交互的套接字
sockfd = socket(AF_INET, SOCK_DGRAM, 0);
if(sockfd <= 0)
{
printf("get ip:sock error\n");
return -1;
}
((struct sockaddr_in *)&ifr.ifr_addr)->sin_family = PF_INET;
通过ioctl()获取指定信息
if(ioctl(sockfd, SIOCGIFADDR, &ifr) < 0)
{
printf("get ip ioctl error\n");
close(sockfd);
return -1;
}
else
{
*ip = ((struct sockaddr_sockaddr_in *)&ifr.ifr_addr)->sin_addr.s_addr;
printf("ip is %s\n", inet_ntoa(((struct sockaddr_sockaddr_in *)&ifr.ifr_addr)->sin_addr));
}
close(sockfd);
return 0;
}
方法二:使用getifaddrs(&ifaddr)
getifaddrs(&ifaddr) 必须与 freeifaddrs(ifaddr);配套使用
int getINCInfo()
{
struct ifaddrs *ifaddr =NULL, *ifa = NULL;
if (getifaddrs(&ifaddr) == -1) {
perror("getifaddrs");
return -1;
}
for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next)
{
if (ifa->ifa_addr == NULL)
continue;
printf("network name is %s\n", ifa_name);
printf("network addr is %s\n", inet_ntoa((((struct sockaddr_in *)(ifa_addr)).sin_addr)));
}
return 0;
}
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 */
};
struct sockaddr与struct sockaddr_in ,struct sockaddr_un的区别和联系
在linux环境下,结构体struct sockaddr在/usr/include/linux/socket.h中定义,具体如下:
typedef unsigned short sa_family_t;
struct sockaddr {
sa_family_t sa_family; /* address family, AF_xxx */
char sa_data[14]; /* 14 bytes of protocol address */
在linux环境下,结构体struct sockaddr_in在/usr/include/netinet/in.h中定义,具体如下:
/* Structure describing an Internet socket address. */
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_);
in_port_t sin_port; /* Port number. */
struct in_addr sin_addr; /* Internet address. */
/* Pad to size of `struct sockaddr'. */
unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) -
sizeof (struct in_addr)];
/* 字符数组sin_zero[8]的存在是为了保证结构体struct sockaddr_in的大小和结构体struct sockaddr的大小相等 */
};
struct sockaddr是通用的套接字地址,而struct sockaddr_in则是internet环境下套接字的地址形式,二者长度一样,都是16个字节。二者是并列结构,指向sockaddr_in结构的指针也可以指向sockaddr。一般情况下,需要把sockaddr_in结构强制转换成sockaddr结构再传入系统调用函数中。