通过裁剪ping命令的源码,实现获取网络状态;ping通,则表示网络状态OK,ping不通,则表示网络状态ERROR:
/*
使用ping 命令源码判断网络状态是否OK
*/
#include <stdio.h>
#include <string.h>
#include <errno.h>
#include <sys/time.h>
#include <netinet/ip_icmp.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <sys/socket.h>
typedef struct pingm_pakcet{
struct timeval tv_begin;
struct timeval tv_end;
short seq;
int32_t flag;
}pingm_pakcet;
static pingm_pakcet pingpacket[128];
static struct sockaddr_in dest;
static int32_t rawsock = 0;
#define HUIP_ADDRESS "192.168.2.99"
static unsigned short network_icmp_cksum(unsigned char *data, int32_t len)
{
int32_t sum = 0;
int32_t odd = len & 0x01;
while(len & 0xfffe){
sum += *(unsigned short*)data;
data += 2;
len -= 2;
}
if(odd){
unsigned short tmp = ((*data)<<8)&0xff00;
sum += tmp;
}
sum = (sum >> 16) + (sum & 0xffff);
sum += (sum >> 16);
return ~sum;
}
static void network_icmp_pack(struct icmp *icmph, int32_t seq, struct timeval *tv, int32_t length)
{
unsigned char i = 0;
icmph->icmp_type = ICMP_ECHO;
icmph->icmp_code = 0;
icmph->icmp_cksum = 0;
icmph->icmp_seq = seq;
icmph->icmp_id = 0 & 0xffff;
for(i=0; i< length; i++)
icmph->icmp_data[i] = i;
icmph->icmp_cksum = network_icmp_cksum((unsigned char*)icmph, length);
LOGDBG("icmph->icmp_cksum =%d\n", icmph->icmp_cksum);// 60672
}
static int32_t network_icmp_send()
{
int32_t i;
short packet_send = 0;
struct timeval tv_begin;
unsigned char send_buff[72];
gettimeofday(&tv_begin, NULL);
int32_t size = 0;
struct timeval tv;
gettimeofday(&tv, NULL);
pingm_pakcet *packet = NULL;
for(i=0; i<128; i++)
{
if(pingpacket[i].flag == 0){
packet = &pingpacket[i];
break;
}
}
if(packet){
packet->seq = packet_send;
packet->flag = 1;
gettimeofday(&packet->tv_begin,NULL);
}
network_icmp_pack((struct icmp *)send_buff,packet_send,&tv, 64);
size = sendto(rawsock, send_buff,64,0,(struct sockaddr *)&dest, sizeof(dest));
if(0 <=size){
LOGDBG("sendto success\n");
packet_send = 1;
}
else
{
LOGERR("sendto error\n");
}
usleep(1000 * 200);
return packet_send;
}
static int32_t network_icmp_recv()
{
int32_t ret = 0;
int32_t status = 1;
struct timeval tv;
unsigned char recv_buff[2*1024];
tv.tv_usec = 200;
tv.tv_sec = 0;
fd_set readfd;
FD_ZERO(&readfd);
FD_SET(rawsock,&readfd);
ret = select(rawsock+1,&readfd,NULL,NULL,&tv);
switch(ret)
{
case -1:
LOGDBG("Network status is ERROR, recvfrom error\n");
status = 0;
break;
case 0:
LOGDBG("Network status is ERROR, recvfrom timeout\n");
status = 0;
break;
default :
{
LOGDBG("Network status is OK\n");
if(recv(rawsock,recv_buff,sizeof(recv_buff),0) <= 0)
{
if(errno == EINTR){
LOGERR("recvfrom error");
}
LOGDBG("Call recv()failed\n");
}
}
break;
}
return status;
}
int main()
{
int32_t retNetworkStatus = 0;
char dest_str[80];
struct protoent *protocol = NULL;
char protoname[] = "icmp";
unsigned long inaddr = 1;
int32_t size = 128*1024;
protocol = getprotobyname(protoname);
if(protocol == NULL)
{
LOGERR("Call getprotobyname() failed");
return false;
}
memset(dest_str, 0x0, sizeof(dest_str));
memcpy(dest_str, HUIP_ADDRESS,strlen(HUIP_ADDRESS)+1);
memset(pingpacket, 0, sizeof(pingm_pakcet) * 128);
rawsock = socket(AF_INET, SOCK_RAW, protocol->p_proto);
if(rawsock < 0){
LOGERR("Call socket() failed");
return false;
}
setsockopt(rawsock, SOL_SOCKET, SO_RCVBUF, &size, sizeof(size));
bzero(&dest, sizeof(dest));
dest.sin_family = AF_INET;
inaddr = inet_addr(HUIP_ADDRESS);
memcpy((char *)&dest.sin_addr, &inaddr,sizeof(inaddr));
inaddr = dest.sin_addr.s_addr;
LOGDBG("PING %s (%ld.%ld.%ld.%ld) 56(84) bytes of data\n",
dest_str,(inaddr&0x000000ff)>>0,(inaddr&0x0000ff00)>>8,(inaddr&0x00ff0000)>>16,(inaddr&0xff000000)>>24);
network_icmp_send();
retNetworkStatus = network_icmp_recv();
//retNetworkStatus 为网络状态情况
return 0;
}