背景

在一些项目中,有时候需要检测网络的一些状态,这里总结了一些常用的方法。

获取网络配置

从配置文件(json文件)获取网络配置,这里使用的是cJson库

static int getNetInfo(char *filename, char *ip, char *gw)
{
	FILE *f;
	long len;
	char *data;
	cJSON *root;
	cJSON *item;
	
	f=fopen(filename,"rb");
	//判断配置文件是否存在,刷机后的第一次是没有配置文件的
	if(f == NULL) {
		ALOGE("Open Config File[%s] Error!\n", filename);
		return -1;
	}
		
	fseek(f,0,SEEK_END);
	len=ftell(f);
	fseek(f,0,SEEK_SET);
	data=(char*)malloc(len+1);
	fread(data,1,len,f);
	fclose(f);
	
	root=cJSON_Parse(data);
	if (!root) {
		ALOGE("Error before: [%s]\n",cJSON_GetErrorPtr());
		return -1;
	}
	else
	{
		item=cJSON_GetObjectItem(root,"terminal_ip");
		memcpy(ip, item->valuestring, strlen(item->valuestring)+1);
		//ALOGV("ip:%s, len:%d\n", item->valuestring, strlen(item->valuestring));
		ALOGV("ip:%s, len:%lu\n", ip, strlen(item->valuestring));
		item=cJSON_GetObjectItem(root,"terminal_gate");
		memcpy(gw, item->valuestring, strlen(item->valuestring)+1);
		ALOGV("gw:%s, len:%lu\n", gw, strlen(item->valuestring));
		//item=cJSON_GetObjectItem(root,"server_ip");
		/*item=cJSON_GetObjectItem(root,"server_ip");
		memcpy(server, item->valuestring, strlen(item->valuestring)+1);
		ALOGV("server_ip:%s, len:%lu\n", server, strlen(item->valuestring));*/
		
		cJSON_Delete(root);
	}
	
	free(data);
	
	return 0;
}

Ping检测

static int ping_status(char *ip)
{
    int i, status;
    pid_t pid;

    // 不同则循环检测多次
    for (i = 0; i < 3; ++i)
    {
        // 新建一个进程来执行ping命令
        if ((pid = vfork()) < 0)
        {
            ALOGE("vfork error");
            continue;
        }
 
        if (pid == 0)
        {
            // 执行ping命令
            if ( execlp("ping", "ping","-c","1",ip, (char*)0) < 0)
            {
                ALOGE("execlp error\n");
                exit(1);
            }
        }
 
        waitpid(pid, &status, 0);
 
        // 相等说明正常
        if (status == 0)
            return 0;
 
      //  sleep(2);
    }
 
    return -1;
}

网络数据包统计

static int net_statistics(char *interface, long *recv, long *send)
{
	FILE* fd = fopen("/proc/net/dev","r+");
	if (NULL == fd)
	{
		ALOGE("/proc/net/dev not exists!\n");
		return -1;
	}
	
	char buf[1024];
	char tempstr[16][16];
	
	memset(buf,0,sizeof(buf));
	memset(tempstr,0,sizeof(tempstr));
	fseek(fd, 0, SEEK_SET);
	int nBytes = fread(buf,1, sizeof(buf)-1,fd);
	if (-1 == nBytes)
	{
		ALOGE("fread error");
		fclose(fd);
		return -1;
	}
	buf[nBytes] = '\0';
	char* pDev = strstr(buf, interface);
	if (NULL == pDev)
	{
		ALOGE("don't find dev %s\n", interface);
		fclose(fd);
		return -1;
	}
	sscanf(pDev,"%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t%[^' ']\t",\
	tempstr[0],tempstr[1],tempstr[2],tempstr[3],tempstr[4],tempstr[5],tempstr[6],tempstr[7],tempstr[8],tempstr[9],tempstr[10],tempstr[11]);
	//*recv = atol(tempstr[1]); //recv bytes		
	//*send = atol(tempstr[9]); //send bytes
	*recv = atol(tempstr[2]); //recv packets		
	*send = atol(tempstr[10]); //send packets
	
	//ALOGV("%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s,%s\n", tempstr[0],tempstr[1],tempstr[2],tempstr[3],tempstr[4],tempstr[5],tempstr[6],tempstr[7],tempstr[8],tempstr[9],tempstr[10],tempstr[11]);

	return 0;
}

网线插拔检测

有两种方式

/*
* 网线插拔检测  
 cat /sys/class/net/eth0/carrier
 
 /proc/net/dev
*/
static int check_cable(char *nic_name)
{
	char cmd_str[256];
	char ret_str[16];
	//char ret = 0;
	
	sprintf(cmd_str, "cat /sys/class/net/%s/carrier", nic_name);
	sys_exec_cmd_buf(cmd_str, (char *)&ret_str, sizeof(ret_str));
	//ret = atoi(ret_str);
	//ALOGV("==>check_cable, cmd:%s ret:%d\n", cmd_str, ret);
	return (ret_str[0] == '1') ? 1:-1;
}

/*
* 网线插拔检测  
*/
static int check_nic(char *nic_name)  
{  
    struct ifreq ifr;  
    int skfd = socket(AF_INET, SOCK_DGRAM, 0);
	if(skfd < 0) {
		//printf("%s:%d Open socket error!\n", __FILE__, __LINE__);
		return -2; 
	}
	
    strcpy(ifr.ifr_name, nic_name);  
    if (ioctl(skfd, SIOCGIFFLAGS, &ifr) < 0)  
    {  
		close(skfd);
        return -2;  
    }  
    if(ifr.ifr_flags & IFF_RUNNING)  
        return 1;  // 网卡已插上网线  
    else 
		return -1;  
} 

路由配置

android和Linux下面的方式会有所不一样。下面为Android下使用ndc的方式,仅供参考。

static int route_config(char *gw)
{
	char cmd_str[256];
	
	//ndc network route add 100 eth0 0.0.0.0/0 192.168.3.1
	sprintf(cmd_str, "ndc network route add 100 eth0 0.0.0.0/0 %s", gw);
	system(cmd_str);
	
	memset(cmd_str, 0, 256);
	//ndc network route add 100 eth0 192.168.3.0/24 #(gateway)
	gw[strlen(gw)-1] = '0';
	ALOGV("==>ndc network route add gw:%s\n", gw);
	sprintf(cmd_str, "ndc network route add 100 eth0 %s/24", gw);
	system(cmd_str);
	
	return 0;
}

获取本机MAC

static int get_local_mac(const char *eth_inf, char *mac)
{
    struct ifreq ifr;
    int sd;

    memset(&ifr, 0, sizeof(struct ifreq));
    if( (sd = socket(AF_INET, SOCK_STREAM, 0)) < 0)
    {
        printf("get %s mac address socket creat error\n", eth_inf);
        return -1;
    }

    strncpy(ifr.ifr_name, eth_inf, sizeof(ifr.ifr_name) - 1);

    if(ioctl(sd, SIOCGIFHWADDR, &ifr) < 0)
    {
        printf("get %s mac address error\n", eth_inf);
        close(sd);
        return -1;
    }

    snprintf(mac, MAC_SIZE, "%02x:%02x:%02x:%02x:%02x:%02x",
        (unsigned char)ifr.ifr_hwaddr.sa_data[0],
        (unsigned char)ifr.ifr_hwaddr.sa_data[1],
        (unsigned char)ifr.ifr_hwaddr.sa_data[2],
        (unsigned char)ifr.ifr_hwaddr.sa_data[3],
        (unsigned char)ifr.ifr_hwaddr.sa_data[4],
        (unsigned char)ifr.ifr_hwaddr.sa_data[5]);

    close(sd);

    return 0;
}

获取本机IP

static int get_local_ip(const char *eth_inf, char *ip)
{
    int sd;
    struct sockaddr_in sin;
    struct ifreq ifr;

    sd = socket(AF_INET, SOCK_DGRAM, 0);
    if (-1 == sd)
    {
        printf("socket error: %s\n", strerror(errno));
        return -1;
    }

    strncpy(ifr.ifr_name, eth_inf, IFNAMSIZ);
    ifr.ifr_name[IFNAMSIZ - 1] = 0;

    // if error: No such device
    if (ioctl(sd, SIOCGIFADDR, &ifr) < 0)
    {
        printf("ioctl error: %s\n", strerror(errno));
        close(sd);
        return -1;
    }

    memcpy(&sin, &ifr.ifr_addr, sizeof(sin));
    snprintf(ip, IP_SIZE, "%s", inet_ntoa(sin.sin_addr));

    close(sd);
    return 0;
}