關於ioctl函數的學習和使用

        在ioctl函數之前,對它的認識是停留在系統調用接口,並無實際更深入的瞭解和掌握,因爲學習和使用,讓我更加清楚了這個函數的“使命”。作爲一個初學者,秉承謙虛好學的態度,希望多多指教,共同進步。廢話不多說了。

        使用:在網絡編程方面,特別是網絡服務器程序對iotcl函數的使用是很經常的,使用iotcl獲取所在主機全部網絡接口的信息,包括:接口地址,是否支持廣播,是否支持多播等等。

        原型:

#include <unistd.h>
int ioctl (int fd, int request,... /*void *arg*/);
                                                                   返回:若成功則爲0,若出錯則爲-1
       參數:

       第一個參數是int fd,使用是需傳入打開的文件描述符,當然包含一般文件,設備文件,以及套接字文件。

       第二個參數是int request,相關網絡的請求參數,網絡請求大體的分爲6類:

                        1. 套接字操作

                        2. 文件操作

                        3. 接口操作

                        4. ARP高速緩存操作

                        5. 路由表操作

                        6. 流系統

        網絡相關的ioctl數據類型如下圖所示:

           第三個參數使用時傳入的是一個指針,該指針的類型是依賴於第二個參數request的,猶如“種瓜得瓜”一般,在第二個參數中輸入對用的套接字文件,接口等數據類型,那當然你需要一個指向套接字文件,接口等數據類型結構的存儲指針。

            實例:

         羅列一些網絡編程經常使用的頭文件包含mynet.h

#include  <netinet/in.h>

#include  <sys/param.h>
#include  <sys/stat.h>
#include  <sys/ioctl.h>
#include  <sys/socket.h>
#include  <sys/socket.h>
#include  <sys/time.h>
#include  <sys/file.h>
#include  <sys/types.h>

#include   <netinet/ip.h>
#include  <arpa/ftp.h>
#include  <arpa/inet.h>
#include  <arpa/telnet.h>
 
#include  <stdio.h>
#include  <signal.h>
#include  <string.h>
#include  <net/if.h>
#include  <stdlib.h>
#include  <unistd.h>
#include  <error.h>
#include <ifaddrs.h>  
#include  <netdb.h>

通過eth0獲取本機的IPv4的地址;

#include "mynet.h"

int main(int argc, char* argv[]){
    char *interface = "eth0";
    struct ifreq ifr;
    int skfd;
    struct sockaddr_in *saddr;
    char printaddr[50];

    if ( (skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
		perror("socket error");
		return -1;
    }

    strncpy(ifr.ifr_name, interface, IFNAMSIZ);
    if (ioctl(skfd, SIOCGIFADDR, &ifr) < 0) {
		perror("net_get_ifaddr: ioctl SIOCGIFADDR");
		close(skfd);
		return -1;
    }
    close(skfd);
	
    saddr = (struct sockaddr_in *) &ifr.ifr_addr;
    inet_ntop(AF_INET,  &saddr->sin_addr, printaddr, sizeof(printaddr));
    printf("IPv4 address: %s\n",  printaddr);
    return 0;
}
通過eth0獲取本機的IPv4的子網掩碼;

#include "mynet.h"

int main(int argc, char* argv[]){
    char *interface = "eth0";
    struct ifreq ifr;
    int skfd;
    struct sockaddr_in *saddr;
    char printaddr[50];

    if ( (skfd = socket(AF_INET, SOCK_DGRAM, 0)) < 0 ) {
        perror("socket error");
        return -1;
    }

    strncpy(ifr.ifr_name, interface, IFNAMSIZ);
    if (ioctl(skfd, SIOCGIFNETMASK, &ifr) < 0) {
        perror("net_get_ifaddr: ioctl SIOCGIFADDR");
        close(skfd);
        return -1;
    }
    close(skfd);
    
    saddr = (struct sockaddr_in *) &ifr.ifr_addr;
    inet_ntop(AF_INET,  &saddr->sin_addr, printaddr, sizeof(printaddr));
    printf("IPv4 netmask: %s\n",  printaddr);
    return 0;
}
通過eth0獲取本機的IPv4的dns;
#include "mynet.h"

int main(int argc, char* argv[]){
	FILE *fp;
	int index = 0;
	char buffer[256] = {0}, dnsname[80] = {0};
	fp = fopen("/etc/resolv.conf", "rb");
	char *printaddr;
	if(!fp){
		printf("IPv4 dns: %s\n", "0.0.0.0");
		return 0;
	}
	while(fgets(buffer, sizeof(buffer), fp)){
		if (sscanf(buffer, "nameserver %s\n", dnsname)){
			printf("IPv4 dns: %s\n", dnsname);
		}
	}
	return 0;	
}

通過eth0獲取本機的IPv6的地址;

include "mynet.h"

int  main(int argc, char *argv[]){  
        struct ifaddrs *ifaddr, *ifa;  
        int family, s;  
        char host[NI_MAXHOST];  
	char* ifaname;     
 
        if (getifaddrs(&ifaddr) == -1){  
            perror("getifaddrs");  
            exit(EXIT_FAILURE);  
        }  
      
        for (ifa = ifaddr; ifa != NULL; ifa = ifa->ifa_next){  
            if (ifa->ifa_addr == NULL)  
                continue;  
      
            family = ifa->ifa_addr->sa_family;  
            ifaname = ifa->ifa_name; 
            if (family == AF_INET6 && memcmp(ifaname, "eth0", 4) == 0 ) {
		printf("%s ", ifa->ifa_name);
		
                s = getnameinfo(ifa->ifa_addr, sizeof(struct sockaddr_in6),  
                        host, NI_MAXHOST, NULL, 0, NI_NUMERICHOST);  
                if (s != 0){  
                    printf("getnameinfo() failed: %s\n", gai_strerror(s));  
                    exit(EXIT_FAILURE);  
                }
		if (memcmp(host, "2001", 4) == 0){                             //add "2001:f80...."
                	printf("\tIPv6 address: <%s>\n", host);  
		}else{
			;
		}	
	    }else{
		continue;
  	    }      
        }  
      
        freeifaddrs(ifaddr);
        exit(EXIT_SUCCESS);  
}  


發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章