Linux网卡的读写编程

Linux网卡的读写编程zz
Linux系统的所有设备都是以文件的形式存在的,所以对系统的操作可以转换为对文件的操作。本程序实现对网卡这个硬件设备进行读取操作,即也是对设备的文件进行读写操作。代码看似麻烦,但却不复杂。
主要的系统函数有:socket(),ioctl(),memcpy(),strcpy()。
两个复杂的结构体:sockaddr_in,ifreq。
.../
#include<stdio.h>
#include<unistd.h>
#include<sys/ioctl.h>
#include<stdlib.h>
#include<sys/socket.h>
#include<netinet/in.h>
#include<arpa/inet.h>
#include<sys/types.h>
#include<net/if.h>
#include<string.h>

unsigned char g_eth_name[16];
unsigned char g_macaddr[6];
unsigned char g_ipaddr;
unsigned char g_subnetmask;
unsigned char g_broadcast_ipaddr;

void init_net(void)
{
int i;
int sock;
struct sockaddr_in sin;
struct ifreq ifr;
sock=socket(AF_INET,SOCK_DGRAM,0);
if(sock==-1)
printf("get the socket file descriptor faild!/n");
strcpy(g_eth_name,"etho");
strcpy(ifr.ifr_name,g_eth_name);
strcpy("eth name:/t%s/n",g_eth_name);

if(ioctl(sock,SIOCGIFHWADDR,&ifr)<0)
printf("get the network card addr faild!/n");
memcpy(g_macaddr,ifr.ifr_hwaddr.sa_data,6);
printf("the network card addr is:");
for(i=0;i<5;i++)
printf("%.2x:",g_macaddr[i]);
printf("%.2x:",g_macaddr[i]);
if(ioctl(sock,SIOCGIFADDR,&ifr)<0)
printf("get the net ip addr faild!/n");
memcpy(&sin,&ifr.ifr_addr,sizeof(sin));
g_ipaddr=sin.sin_addr.s_addr;
printf("local eth0:/t%s/n",inet_ntoa(sin.sin_addr));

if(ioctl(sock,SIOCGIFBRDADDR,&ifr)<0)
printf("get the broadcast ip addr faild!/n");
memcpy(&sin,&ifr.ifr_addr,sizeof(sin));
g_broadcast_ipaddr=sin.sin_addr.s_addr;
printf("broadcast:/t%s/n",inet_ntoa(sin.sin_addr));
if(ioctl(sock,SIOCGIFNETMASK,&ifr)<0)
printf("get the netsubmask faild!/n");
memcpy(&sin,&ifr.ifr_addr,sizeof(sin));
g_subnetmask=sin.sin_addr.s_addr;
printf("subnetmask:/t%s/n",inet_ntoa(sin.sin_addr));

close(sock);

}
int main()
{
init_net();
return 0;
}
代码虽长,但结构很简单。先要明白这个程序的功能是什么,这个程序是用来读取网卡的信息,其中包括网卡的ip地址,网卡的名称,网卡的MAC,网卡的子网掩码,网卡的广播地址。
代码首先包涵所必须的头文件,那些头文件可以在你要用那个系统函数时用man命令来找到。开头先定
所有记录信息的变量。
g_eth_name是网卡的名称
g_macaddr 是网卡的MAC
下面三个整型分别是子网掩码地址,网络ip地址,广播地址。接着在init_net()函数里面进行所有的操作。
首先定义一个int 的sock,这个sock好比文件的文件描述符一样。即它是网卡文件的描述符。
struct sockaddr_in 在系统的/usr/include/netinet/in.h里
struct sockaddr_in
{
__SOCKADDR_COMMON (sin_);
in_port_t sin_port;
struct in_addr sin_addr;


unsigned char sin_zero[sizeof (struct sockaddr) -
__SOCKADDR_COMMON_SIZE -
sizeof (in_port_t) -
sizeof (struct in_addr)];
};
而里面的in_addr结构 in_addr 定义为//它也在/usr/include/netinet/in.h
struct in_addr{
in_addr_t s_addr;
};
其中in_addr_t 在in.h里为typedef uint32_t in_addr_t;这里的uint32_t,其中u是指unsigned,int为整型,32即为长整型所以uint32=unsigend long int 即in_addr_t s_addr=unsigend long int s_addr;
所以struct in_addr的实际定义为:
struct in_addr{
unsigend long int s_addr;
};
第二个结构体定义在/usr/include/net/if.h里

struct ifreq
{
# define IFHWADDRLEN 6
# define IFNAMSIZ IF_NAMESIZE
union
{
char ifrn_name[IFNAMSIZ];
} ifr_ifrn;

union
{
struct sockaddr ifru_addr;
struct sockaddr ifru_dstaddr;
struct sockaddr ifru_broadaddr;
struct sockaddr ifru_netmask;
struct sockaddr ifru_hwaddr;
short int ifru_flags;
int ifru_ivalue;
int ifru_mtu;
struct ifmap ifru_map;
char ifru_slave[IFNAMSIZ];
char ifru_newname[IFNAMSIZ];
__caddr_t ifru_data;
} ifr_ifru;
};
代码用socket函数得到网卡的设备描述符存入sock里。在你的机器开启进入系统后,系统就会用你设置的网卡名来填充这个结构体,所以可以直接打印这个结构体里的ifr.ifr_name
接下来是获取网卡的MAC,用ioctl函数。这函数有三个参数,第一个是网卡的设备描述符,第三个是包涵网卡信息的ifreq结构体。第二个参数是设置索引,即你要获取的网卡信息种类。分别为
SIOCGIFHWADDR //为MAC地址
SIOCGIFADDR//为IP地址
SIOCGIFBRDADDR//为广播地址
SIOCGIFNETMASK//为子网掩码
每个获取后用memcpy函数COPY到前面定义的变量当中存储起来。然后 打印。
在main函数里调用 init_net()。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值