通过ping 命令源码获取网络状态

通过裁剪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;
}

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值