Linux&Android网络检测相关

背景

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

获取网络配置

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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
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检测

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
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;
}

网络数据包统计

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
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;
}

网线插拔检测

有两种方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
/*
* 网线插拔检测
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的方式,仅供参考。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
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

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
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;
}
Donate comment here