ioctl在socket中的一些用法及示例


-------------------------------------------------------------------
ioctl在socket中的一些用法及示例

函數 : ioctl(int fd, int request, void * arg)
定義 : <sys/ioctl.h>
功能 : 控制I/O設備, 提供了一種獲得設備信息和向設備發送控制參數的手段.
參數 : int  fd      文件句柄. 用於socket時, 是socket套接字.
       int  request 函數定義的所有操作. 關於socket的操作, 定義在<linux/sockios.h>文件中.
       void *arg    指針的類型依賴於request參數.
 
以下表格從網上收集了request - arg指針類型的對應關系

類別

Request

說明

數據類型

 
 

SIOCATMARK 
SIOCSPGRP 
SIOCGPGRP

是否位於帶外標記 
設置套接口的進程ID 或進程組ID 
獲取套接口的進程ID 或進程組ID

int 
int 
int

 

FIONBIN 
FIOASYNC 
FIONREAD 
FIOSETOWN 
FIOGETOWN

設置/ 清除非阻塞I/O 標志 
設置/ 清除信號驅動異步I/O 標志 
獲取接收緩存區中的字節數 
設置文件的進程ID 或進程組ID 
獲取文件的進程ID 或進程組ID

int 
int 
int 
int 
int

 

SIOCGIFCONF 
SIOCSIFADDR 
SIOCGIFADDR 
SIOCSIFFLAGS 
SIOCGIFFLAGS 
SIOCSIFDSTADDR 
SIOCGIFDSTADDR 
SIOCGIFBRDADDR 
SIOCSIFBRDADDR 
SIOCGIFNETMASK 
SIOCSIFNETMASK 
SIOCGIFMETRIC 
SIOCSIFMETRIC 
SIOCGIFMTU 
SIOCxxx

獲取所有接口的清單 
設置接口地址 
獲取接口地址 
設置接口標志 
獲取接口標志 
設置點到點地址 
獲取點到點地址 
獲取廣播地址 
設置廣播地址 
獲取子網掩碼 
設置子網掩碼 
獲取接口的測度 
設置接口的測度 
獲取接口MTU 
(還有很多取決於系統的實現)

struct ifconf 
struct ifreq 
struct ifreq 
struct ifreq 
struct ifreq 
struct ifreq 
struct ifreq 
struct ifreq 
struct ifreq 
struct ifreq 
struct ifreq 
struct ifreq 
struct ifreq 
struct ifreq

ARP

SIOCSARP 
SIOCGARP 
SIOCDARP

創建/ 修改ARP 表項 
獲取ARP 表項 
刪除ARP 表項

struct arpreq 
struct arpreq 
struct arpreq

 

SIOCADDRT 
SIOCDELRT

增加路徑 
刪除路徑

struct rtentry 
struct rtentry

I_xxx

 

 

socket最常用到的結構體: struct ifreq 定義在<net/if.h>.(包括struct ifconf/ifr_flags等的定義)

 

一、獲取

以下例程通過ioctl獲取設備"eth0"的IP/掩碼/硬件址

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

#include "net/if.h"
#include "arpa/inet.h"
#include "linux/sockios.h"

int main(int argc,char *argv[])
{
    struct sockaddr_in *addr;
    struct ifreq ifr;
    char*address;
    int sockfd;

    char *name = "eth0";
    if( strlen(name) >= IFNAMSIZ)
        printf("device name is error.\n"), exit(0);
        
    strcpy( ifr.ifr_name, name);
        
    sockfd = socket(AF_INET,SOCK_DGRAM,0);

    //get inet addr
    if( ioctl( sockfd, SIOCGIFADDR, &ifr) == -1)
        printf("ioctl error.\n"), exit(0);

    addr = (struct sockaddr_in *)&(ifr.ifr_addr);
    address = inet_ntoa(addr->sin_addr);

    printf("inet addr: %s\n",address);

    //get Mask
    if( ioctl( sockfd, SIOCGIFNETMASK, &ifr) == -1)
        printf("ioctl error.\n"), exit(0);

    addr = (struct sockaddr_in *)&ifr.ifr_addr;
    address = inet_ntoa(addr->sin_addr);

    printf("Mask: %s\n",address);

    //get HWaddr 
    u_int8_t hd[6];
    if(ioctl(sockfd, SIOCGIFHWADDR, &ifr) == -1)
        printf("hwaddr error.\n"), exit(0);

    memcpy( hd, ifr.ifr_hwaddr.sa_data, sizeof(hd));
    printf("HWaddr: %02X:%02X:%02X:%02X:%02X:%02X\n", hd[0], hd[1], hd[2], hd[3], hd[4], hd[5]);
    
    exit(0);
}

  

 

 二、設置

以下例程設置eth0的IP地址.

#include "stdio.h"
#include "stdlib.h"
#include "string.h"

#include "net/if.h"
#include "arpa/inet.h"
#include "linux/sockios.h"

int main(int argc,char *argv[])
{
    char *dev = "eth0";
    char *ip = "192.168.1.252";
    
    struct ifreq ifr;
    if( strlen(dev) >= IFNAMSIZ)
        printf("device name error.\n"), exit(0);
    else
        strcpy( ifr.ifr_name, dev);
    
    int sockfd = socket(AF_INET,SOCK_DGRAM,0);

    //get inet addr
    if( ioctl( sockfd, SIOCGIFADDR, &ifr) == -1)
        printf("ioctl error.\n"), exit(0);
    
    struct sockaddr_in *addr = (struct sockaddr_in *)&(ifr.ifr_addr);
    char * address = inet_ntoa(addr->sin_addr);

    printf("current inet addr: %s\n",address);

    //set inet addr
    struct sockaddr_in *p = (struct sockaddr_in *)&(ifr.ifr_addr);

    p->sin_family = AF_INET;
    inet_aton( ip, &(p->sin_addr));

    if( ioctl( sockfd, SIOCSIFADDR, &ifr) == -1)
     printf("ioctl error.\n"), exit(0);
    else    
        printf("change inet addr to: %s\n", ip);

    //any OS need active dev.
    /*ifr.ifr_flags |= IFF_UP;
    if( ioctl( sockfd, SIOCSIFFLAGS, &ifr) == -1)
        printf("active fault.\n"), exit(0);
    else
        printf("%s[%s] is working...\n", dev, ip);
    */
        
    close(sockfd);
    exit(1);
    //end
}

  

屏蔽的代碼用於設置IP后, 激活新設置. 多數系統不需要這步操作. 
而且這步僅作演示. 真實使用的時候, 至少應該
1. 獲取當前ifr.ifr_flags
2. ifr.ifr_flags |= IFF_UP;

以上是ioctl的一些示例, 實戰中靈活使用、舉一反三.


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM