ioctl 获取本机网卡ip地址 | socket() 复制代码

<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);"></span><pre name="code" class="cpp">#include <string.h>
#include <sys/socket.h>
#include <sys/ioctl.h>
#include <net/if.h>
#include <stdio.h>
#include <netinet/in.h>
#include <arpa/inet.h>
int main()
{
    int inet_sock;
    struct ifreq ifr;
    inet_sock = socket(AF_INET, SOCK_DGRAM, 0); 
    //eth0为接口到名称

    strcpy(ifr.ifr_name, "eth1");

    //SIOCGIFADDR标志代表获取接口地址

    if (ioctl(inet_sock, SIOCGIFADDR, &ifr) ==  0)  
        perror("ioctl");

    printf("%s\n", inet_ntoa(((struct sockaddr_in*)&(ifr.ifr_addr))->sin_addr)); //转换成点分十进制的格式
    return 0;
}
 
<span style="font-family: Arial, Helvetica, sans-serif; background-color: rgb(255, 255, 255);">--------------------------------------------------------------------------------------------------------------------------------------------------------------</span>

ifreq结构定义在/usr/include/net/if.h,用来配置ip地址,激活接口,配置MTU等接口信息的。
其中包含了一个接口的名字和具体内容——(是个共用体,有可能是IP地址,广播地址,子网掩码,MAC号,MTU或其他内容)。
ifreq包含在ifconf结构中。而ifconf结构通常是用来保存所有接口的信息的。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

用ioctl获得本地ip地址时要用到两个结构体ifconf和ifreq,它们对于大多数人
来说都是比较陌生的,这里给大家一种比较简单的理解方法,当然只一种帮助
理解的方法,在描述中可能会有一些地方与真实定义有所出入,仅供参考.

首先先认识一下ifconf和ifreq:

//ifconf通常是用来保存所有接口信息的
//if.h
struct ifconf 
{
    int    ifc_len;            /* size of buffer    */
    union 
    {
        char *ifcu_buf;                        /* input from user->kernel*/
        struct ifreq *ifcu_req;        /* return from kernel->user*/
    } ifc_ifcu;
};
#define    ifc_buf    ifc_ifcu.ifcu_buf        /* buffer address    */
#define    ifc_req    ifc_ifcu.ifcu_req        /* array of structures    */
 
//ifreq用来保存某个接口的信息
//if.h
struct ifreq {
    char ifr_name[IFNAMSIZ];
    union {
        struct sockaddr ifru_addr;
        struct sockaddr ifru_dstaddr;
        struct sockaddr ifru_broadaddr;
        short ifru_flags;
        int ifru_metric;
        caddr_t ifru_data;
    } ifr_ifru;
};
#define ifr_addr ifr_ifru.ifru_addr
#define ifr_dstaddr ifr_ifru.ifru_dstaddr
#define ifr_broadaddr ifr_ifru.ifru_broadaddr

 

上边这两个结构看起来比较复杂,我们现在把它们简单化一些:
比如说现在我们向实现获得本地IP的功能。

我们的做法是:
1. 先通过ioctl获得本地所有接口的信息,并保存在ifconf中
2. 再从ifconf中取出每一个ifreq中表示ip地址的信息

具体使用时我们可以认为ifconf就有两个成员:
ifc_len 和 ifc_buf,
如图一所示:    

  

ifc_len:表示用来存放所有接口信息的缓冲区长度
ifc_buf:表示存放接口信息的缓冲区

所以我们需要在程序开始时对ifconf的ifc_led和ifc_buf进行初始化
接下来使用ioctl获取所有接口信息,完成后ifc_len内存放实际获得的借口信息总长度
并且信息被存放在ifc_buf中。

如下图示:(假设读到两个接口信息)


接下来我们只需要从一个一个的接口信息获取ip地址信息即可。

下面有一个简单的参考:

#include 
#include 
#include 
#include 
#include in.h>
#include <string.h>
#include if.h>
#include 
 
int main()
{
    int i=0;
    int sockfd;
  struct ifconf ifconf;
  unsigned char buf[512];
  struct ifreq *ifreq;
  
  //初始化ifconf
  ifconf.ifc_len = 512;
  ifconf.ifc_buf = buf;
  
    if((sockfd = socket(AF_INET, SOCK_DGRAM, 0))<0)
    {
        perror("socket");
        exit(1);
    }  
  ioctl(sockfd, SIOCGIFCONF, &ifconf);    //获取所有接口信息
  
  //接下来一个一个的获取IP地址
  ifreq = (struct ifreq*)buf;  
  for(i=(ifconf.ifc_len/sizeof(struct ifreq)); i>0; i--)
  {
//      if(ifreq->ifr_flags == AF_INET){            //for ipv4
          printf("name = [%s]\n", ifreq->ifr_name);
      printf("local addr = [%s]\n", 
                      inet_ntoa(((struct sockaddr_in*)&(ifreq->ifr_addr))->sin_addr));
      ifreq++;
//  }
  }
    return 0;
}
 
此方法仅供参考,也适用于获取其他信息。

--------------------------------------------------------------------------------------------------------------------------------------------------------------

简述:
创建一个套接口。
#include <winsock.h>
SOCKET PASCAL FAR socket( int af, int type, int protocol);
af:一个地址描述。目前仅支持AF_INET格式,也就是说ARPA Internet地址格式。
type:新套接口的类型描述。
protocol:套接口所用的协议。如调用者不想指定,可用0。

注释


   socket()函数用于根据指定的地址族、数据类型和协议来分配一个套接口的描述字及其所用的资源。如果协议protocol未指定(等于0),则使用缺省的连接方式。
对于使用一给定地址族的某一特定套接口,只支持一种协议。但地址族可设为AF_UNSPEC(未指定),这样的话协议参数就要指定了。协议号特定于进行通讯的“通讯域”。支持下述类型描述:
类型 解释
SOCK_STREAM 提供有序的、可靠的、双向的和基于连接的字节流,使用带外数据传送机制,为Internet地址族使用TCP。
SOCK_DGRAM 支持无连接的、不可靠的和使用固定大小(通常很小)缓冲区的数据报服务,为Internet地址族使用UDP。
SOCK_STREAM类型的套接口为全双向的字节流。对于流类套接口,在接收或发送数据前必需处于已连接状态。用 connect()调用建立与另一套接口的连接,连接成功后,即可用 send()和recv()传送数据。当会话结束后,调用closesocket()。带外数据根据规定用send()和recv()来接收。
实现SOCK_STREAM类型套接口的通讯协议保证数据不会丢失也不会重复。如果终端协议有缓冲区空间,且数据不能在一定时间成功发送,则认为连接中断,其后续的调用也将以WSAETIMEOUT错误返回。
SOCK_DGRAM类型套接口允许使用 sendto()和recvfrom()从任意端口发送或接收数据报。如果这样一个套接口用connect()与一个指定端口连接,则可用send()和recv()与该端口进行数据报的发送与接收。

返回值


  若无错误发生,socket()返回引用新套接口的描述字。否则的话,返回INVAID_SOCKET错误,应用程序可通过WSAGetLastError()获取相应错误代码。
错误代码:
WSANOTINITIALISED:在使用此API之前应首先成功地调用WSAStartup()。
WSAENETDOWN:WINDOWS套接口实现检测到网络子系统失效。
WSAEAFNOSUPPORT:不支持指定的地址族。
WSAEINPROGRESS:一个阻塞的WINDOWS套接口调用正在运行中。
WSAEMFILE:无可用文件描述字。
WSAENOBUFS:无可用缓冲区,无法创建套接口。
WSAEPROTONOSUPPORT:不支持指定的协议。
WSAEPROTOTYPE:指定的协议不适用于本套接口。
WSAESOCKTNOSUPPORT:本地址族中不支持该类型套接口。

参见


   accept(), bind(), connect(), getsockname(), getsockopt(), setsockopt(), listen(), recv(), recvfrom(), select(), send(), sendto(), shutdown(), ioctlsocket().4.2 数据库例程
socket()
函数原型:
SOCKET WSAAPI  socket(
int af,
int type,
int protocol
);
该函数及参数定义包含在winsock2.h头文件中,在MSDN中查不到具体参数。
参数选项及定义:
地址族af:(常用AF_INET实现TCP/UDP协议)
#define AF_UNSPEC       0               /* unspecified */
#define AF_UNIX         1               /* local to host (pipes, portals) */
#define AF_INET         2               /* internetwork: UDP, TCP, etc. */
#define AF_IMPLINK      3               /* arpanet imp addresses */
#define AF_PUP          4               /* pup protocols: e.g. BSP */
#define AF_CHAOS        5               /* mit CHAOS protocols */
#define AF_NS           6               /* XEROX NS protocols */
#define AF_IPX          AF_NS           /* IPX protocols: IPX, SPX, etc. */
#define AF_ISO          7               /* ISO protocols */
#define AF_OSI          AF_ISO          /* OSI is ISO */
#define AF_ECMA         8               /* european computer manufacturers */
#define AF_DATAKIT      9               /* datakit protocols */
#define AF_CCITT        10              /* CCITT protocols, X.25 etc */
#define AF_SNA          11              /* IBM SNA */
#define AF_DECnet       12              /* DECnet */
#define AF_DLI          13              /* Direct data link interface */
#define AF_LAT          14              /* LAT */
#define AF_HYLINK       15              /* NSC Hyperchannel */
#define AF_APPLETALK    16              /* AppleTalk */
#define AF_NETBIOS      17              /* NetBios-style addresses */
#define AF_VOICEVIEW    18              /* VoiceView */
#define AF_FIREFOX      19              /* Protocols from Firefox */
#define AF_UNKNOWN1     20              /* Somebody is using this! */
#define AF_BAN          21              /* Banyan */
#define AF_ATM          22              /* Native ATM Services */
#define AF_INET6        23              /* Internetwork Version 6 */
#define AF_CLUSTER      24              /* Microsoft Wolfpack */
#define AF_12844        25              /* IEEE 1284.4 WG AF */
套接字类型type:
#define SOCK_STREAM     1               /* stream socket */
#define SOCK_DGRAM      2               /* datagram socket */
#define SOCK_RAW        3               /* raw-protocol interface */
#define SOCK_RDM        4               /* reliably-delivered message */
#define SOCK_SEQPACKET  5               /* sequenced packet stream */
协议类型protocol:
#define IPPROTO_IP              0               /* dummy for IP */
#define IPPROTO_ICMP            1               /* control message protocol */
#define IPPROTO_IGMP            2               /* internet group management protocol */
#define IPPROTO_GGP             3               /* gateway^2 (deprecated) */
#define IPPROTO_TCP             6               /* tcp */
#define IPPROTO_PUP             12              /* pup */
#define IPPROTO_UDP             17              /* user datagram protocol */
#define IPPROTO_IDP             22              /* xns idp */
#define IPPROTO_ND              77              /* UNOFFICIAL net disk proto */

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值