network模块小节

         网络是很多电子产品应用的基础,因此尤为重要。近期做的互联网电视项目 也是在建立在网络连接的基础之上,可惜我做的只是简单的porting层工作,对各种网络协议、应用以及底层驱动知之甚少。在这里小结一下network模块的工作流程。

        首先设备启动的时候会创建一个线程用来检测网络连接的状态,当网线拔出或者插上以及ip地址发生变化就会向显示界面发送相应的消息。目前是通过获取上一次网络连接状态和当前网络连接状态进行比较来判断该发送的消息类型,通过功能强大的ioctl函数。感觉这种实现方法不太好,可能会增加网卡的负担。接下来是获取DNS/IP/MAC/GATEWAY,如果获取不到IP说明网卡设备还没有正式进入工作状态,网络连接也还没有正式连通,因此需要在这里等待直到获取到IP或者能判断网络通,然后就向显示界面发送一条指定的消息,实现从初始化页面向主页面的跳转。因为进行网络连接的工作都是底层完成的,所以我的porting层的实际上只需要做对网络状态是否发生变化(插拔网线)进行检测,以及开机后等待直到网络连通之后发送跳转消息给界面的工作。

        这个过程中用到了几个通用的函数:

struct  ifreq
{
        #ifndef IFNAMSIZ
        #define IFNAMSIZ        16
        #endif

        char  ifr_name[IFNAMSIZ];
 
        union {
                struct  sockaddr ifru_addr;
                struct  sockaddr ifru_dstaddr;
                struct  sockaddr ifru_broadaddr;
                __ulong32_t      ifru_flags;
                int              ifru_metric;
                caddr_t          ifru_data;
                u_short          ifru_site6;
                __ulong32_t      ifru_mtu;
                int              ifru_baudrate;
} ifr_ifru;

 

 

一、检测网卡工作状态(物理连接)

#include <stdio.h> #include <string.h> #include <stdlib.h> #include <errno.h> #include <unistd.h> #include <sys/types.h> #include <sys/socket.h> #include <netinet/in.h> #include <arpa/inet.h> #include <sys/ioctl.h> #include <net/if.h>

 

1.通过SIOCGIFFLAGS

static int network_get_netlink_status(const char *if_name) { int skfd; struct ifreq ifr = {0}; if ((skfd = socket(AF_INET,SOCK_STREAM,0)) < 0) { fprintf(stderr,"socket create failed/n"); return LINK_ERR; } strcpy(ifr.ifr_name, if_name); if (ioctl(skfd,SIOCGIFFLAGS,&ifr) < 0) { fprintf("SIOCGIFFLAGS failed: %s/n", strerror(errno)); close(skfd); return LINK_ERR; } if (ifr.ifr_ifru.ifru_flags & IFF_RUNNING) return LINK_UP; else return LINK_DOWN; }

2.通过SIOCETHTOOL

static int network_detect_ethtool(int skfd, const char *if_name) { struct ifreq ifr; struct ethtool_value edata; memset(&ifr, 0, sizeof(ifr)); edata.cmd = ETHTOOL_GLINK; strncpy(ifr.ifr_name, if_name, sizeof(ifr.ifr_name)-1); ifr.ifr_data = (char *)&edata; if (ioctl(skfd, SIOCETHTOOL, &ifr) == -1) { printf("ETHTOOL_GLINK failed: %s/n", strerror(errno)); return 2; } return edata.data; }

3.通过SIOCGMIIREG

static int network_detect_mii(int skfd,const char *ifname) { struct ifreq ifr = {0}; unsigned phy_id; unsigned short *data, mii_val; strncpy(ifr.ifr_name, ifname, IFNAMSIZ); if (ioctl(skfd, SIOCGMIIPHY, &ifr) < 0) { fprintf(stderr, "SIOCGMIIPHY failed: %s/n",strerro(errno)); (void) close(skfd); return 2; } data = (u16 *)(&ifr.ifr_data); phy_id = data[0]; data[1] = 1; if (ioctl(skfd, SIOCGMIIREG, &ifr) < 0) { fprintf(stderr, "SIOCGMIIREG failed: %s/n", strerror(errno)); return 2; } // mii_val |= data[3]; mii_val = data[3]; return(((mii_val & 0x0016) == 0x0004) ? 0 : 1); }

 

二、检测接口的inet addr,Bcast ,Mask

const int network_get_eth_info(const char *if_name) { int sockfd; char *address = NULL; struct ifreq ifr = {0}; struct sockaddr_in *addr = {0}; if ((sockfd = socket(AF_INET,SOCK_STREAM,0)) < 0) { printf("socket create failed."); return 2; } strncpy(ifr.ifr_name,if_name,IFNAMSIZ-1); if(ioctl(sockfd,SIOCGIFADDR,&ifr) < 0) { printf("SIOCGIFADDR on %s failed: %s/n", if_name, strerror(errno)); return 2; } addr = (struct sockaddr_in *)&(ifr.ifr_addr); address = inet_ntoa(addr->sin_addr); printf("inet addr: %s ",address); if(ioctl(sockfd,SIOCGIFBRDADDR,&ifr) < 0) { printf("SIOCGIFADDR on %s failed: %s/n", if_name, strerror(errno)); return 2; } addr = (struct sockaddr_in *)&ifr.ifr_broadaddr; address = inet_ntoa(addr->sin_addr); printf("Bcast: %s ",address); if(ioctl(sockfd,SIOCGIFNETMASK,&ifr) < 0) { printf("SIOCGIFADDR on %s failed: %s/n", if_name, strerror(errno)); return 2; } addr = (struct sockaddr_in *)&ifr.ifr_addr; address = inet_ntoa(addr->sin_addr); printf("Mask: %s ",address); printf("/n"); return 0; }

三、检测接口的MAC地址

static int network_get_mac(const char *if_name, void *arg) { int skfd; u_char * ptr; char *mac = (char *)arg; struct ifreq ifr = {0}; if (NULL == arg) { fprintf(stderr, "(out)arg is null"); return -1; } if ((skfd = socket(AF_INET,SOCK_STREAM,0)) < 0) { fprintf(stderr, "create socket failed/n"); return -1; } strcpy(ifr.ifr_name, if_name); if (ioctl(skfd,SIOCGIFHWADDR,&ifr) < 0) { fprintf(stderr, "(out)SIOCGIFHWADDR failed: %s", strerror(errno)); return -1; } ptr =(u_char *)&ifr.ifr_ifru.ifru_hwaddr.sa_data[0]; sprintf(mac, "%02x-%02x-%02x-%02x-%02x-%02x",*ptr,*(ptr+1),*(ptr+2),*(ptr+3),*(ptr+4),*(ptr+5)); return 0; }

四、获取网卡设备名

static int network_get_interface_name(char (*interface_name)[10]) { int skfd; int i, len, count; char *ifreq_pointer = NULL; struct ifreq *result = NULL; struct ifconf get_info = {0}; len = 10 * sizeof(struct ifreq); ifreq_pointer = (char *)calloc(1, len); get_info.ifc_len = len; get_info.ifc_ifcu.ifcu_buf = ifreq_pointer; if ((skfd = socket(AF_INET,SOCK_STREAM,0)) < 0) { fprintf(stderr, "create socket failed/n"); free(ifreq_pointer); ifreq_pointer = NULL; return -1; } if (ioctl(skfd, SIOCGIFCONF, &get_info) < 0) { fprintf(stderr, "SIOCGIFCONF failed: %s", strerror(errno)); free(ifreq_pointer); ifreq_pointer = NULL; return -1; } count = get_info.ifc_len / sizeof(struct ifreq); result = (struct ifreq *)ifreq_pointer; for(i=0; i<count; i++) { strcpy(interface_name[i], result[i].ifr_name); fprintf(stderr, "the %d interface name: %s/n", i, interface_name[i]); } free(ifreq_pointer); ifreq_pointer = NULL; return count; } void main() { int count = 0; char eth_name[5][10] = {0}; count = network_get_interface_name(eth_name); }

五、获取IP地址

static int network_get_ipaddr(char *interface_name, char *ipaddr)
{
	int sockfd;
	
	struct ifreq ifr;
	struct sockaddr_in *sin;

	if((NULL == interface_name) || (NULL == ipaddr))
	{
		printf("Error argument \n");
		return -1;
	}
	
	sockfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(sockfd < 0)
	{
		printf("Socket error \n");
		return -1;
	}	
	
	bzero((char *)&ifr, sizeof(ifr));
	strcpy(ifr.ifr_name, interface_name);
	
	if (ioctl(sockfd, SIOCGIFADDR, &ifr) < 0)
	{
		printf("ioctl SIOCGIFADDR failed: %s", strerror(errno));
		return -1;
	}
	
#if 1
	sin = (struct sockaddr_in *)&ifr.ifr_addr;
	strcpy(ipaddr, (char *)inet_ntoa(sin->sin_addr));
	
#else
	struct sockaddr_in * ptr;
	ptr = (struct sockaddr_in *)&(ifr.ifr_ifru.ifru_addr);
	memcpy((char*)ipaddr, (char*)&ptr->sin_addr, sizeof(unsigned long));
	*ipaddr = swap32(*ipaddr);
	printf("IP = %s \n",inet_ntoa(ptr->sin_addr));
#endif

	close(sockfd);
	
	return 0;
}


 

你可能感兴趣的:(struct,socket,网络,NetWork,interface)