1. 程式人生 > >ioctl在socket中的一些用法及示例

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

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


函式 : ioctl(int fd, int request, void * arg)
定義 : 
功能 : 控制I/O裝置, 提供了一種獲得裝置資訊和向裝置傳送控制引數的手段.
引數 : int  fd      檔案控制代碼. 用於socket時, 是socket套接字.
       int  request 函式定義的所有操作. 關於socket的操作, 定義在檔案中.
       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 定義在.(包括struct ifconf/ifr_flags等的定義)

 

一、獲取

以下例程通過ioctl獲取裝置"eth0"的IP/掩碼/硬體址

  1. #include "stdio.h"
  2. #include "stdlib.h"
  3. #include "string.h"
  4.  
  5. #include "net/if.h"
  6. #include "arpa/inet.h"
  7. #include "linux/sockios.h"
  8.  
  9. int main(int argc,char *argv[])
  10. {
  11.     struct sockaddr_in *addr;
  12.     struct ifreq ifr;
  13.     char*address;
  14.     int sockfd;
  15.  
  16.     char *name = "eth0";
  17.     if( strlen(name) >= IFNAMSIZ)
  18.         printf("device name is error.\n"), exit(0);
  19.         
  20.     strcpy( ifr.ifr_name, name);
  21.         
  22.     sockfd = socket(AF_INET,SOCK_DGRAM,0);
  23.  
  24.     //get inet addr
  25.     if( ioctl( sockfd, SIOCGIFADDR, &ifr) == -1)
  26.         printf("ioctl error.\n"), exit(0);
  27.  
  28.     addr = (struct sockaddr_in *)&(ifr.ifr_addr);
  29.     address = inet_ntoa(addr->sin_addr);
  30.  
  31.     printf("inet addr: %s\n",address);
  32.  
  33.     //get Mask
  34.     if( ioctl( sockfd, SIOCGIFNETMASK, &ifr) == -1)
  35.         printf("ioctl error.\n"), exit(0);
  36.  
  37.     addr = (struct sockaddr_in *)&ifr.ifr_addr;
  38.     address = inet_ntoa(addr->sin_addr);
  39.  
  40.     printf("Mask: %s\n",address);
  41.  
  42.     //get HWaddr 
  43.     u_int8_t hd[6];
  44.     if(ioctl(sockfd, SIOCGIFHWADDR, &ifr) == -1)
  45.         printf("hwaddr error.\n"), exit(0);
  46.  
  47.     memcpy( hd, ifr.ifr_hwaddr.sa_data, sizeof(hd));
  48.     printf("HWaddr: %02X:%02X:%02X:%02X:%02X:%02X\n", hd[0], hd[1], hd[2], hd[3], hd[4], hd[5]);
  49.     
  50.     exit(0);
  51. }


 二、設定

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

  1. #include "stdio.h"
  2. #include "stdlib.h"
  3. #include "string.h"
  4.  
  5. #include "net/if.h"
  6. #include "arpa/inet.h"
  7. #include "linux/sockios.h"
  8.  
  9. int main(int argc,char *argv[])
  10. {
  11.     char *dev = "eth0";
  12.     char *ip = "192.168.1.252";
  13.     
  14.     struct ifreq ifr;
  15.     if( strlen(dev) >= IFNAMSIZ)
  16.         printf("device name error.\n"), exit(0);
  17.     else
  18.         strcpy( ifr.ifr_name, dev);
  19.     
  20.     int sockfd = socket(AF_INET,SOCK_DGRAM,0);
  21.  
  22.     //get inet addr
  23.     if( ioctl( sockfd, SIOCGIFADDR, &ifr) == -1)
  24.         printf("ioctl error.\n"), exit(0);
  25.     
  26.     struct sockaddr_in *addr = (struct sockaddr_in *)&(ifr.ifr_addr);
  27.     char * address = inet_ntoa(addr->sin_addr);
  28.  
  29.     printf("current inet addr: %s\n",address);
  30.  
  31.     //set inet addr
  32.     struct sockaddr_in *= (struct sockaddr_in *)&(ifr.ifr_addr);
  33.  
  34.     p->sin_family = AF_INET;
  35.     inet_aton( ip, &(p->sin_addr));
  36.  
  37.     if( ioctl( sockfd, SIOCSIFADDR, &ifr) == -1)
  38.      printf("ioctl error.\n"), exit(0);
  39.     else    
  40.         printf("change inet addr to: %s\n", ip);
  41.  
  42.     //any OS need active dev.
  43.     /*ifr.ifr_flags |= IFF_UP;
  44.     if( ioctl( sockfd, SIOCSIFFLAGS, &ifr) == -1)
  45.         printf("active fault.\n"), exit(0);
  46.     else
  47.         printf("%s[%s] is working...\n", dev, ip);
  48.     */
  49.         
  50.     close(sockfd);
  51.     exit(1);
  52.     //end
  53. }

遮蔽的程式碼用於設定IP後, 啟用新設定. 多數系統不需要這步操作. 
而且這步僅作演示. 真實使用的時候, 至少應該
1. 獲取當前ifr.ifr_flags
2. ifr.ifr_flags |= IFF_UP;

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