欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

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

程序员文章站 2024-01-23 18:38:10
...

通过裁剪ping命令的源码,实现获取网络状态;ping通,则表示网络状态OK,ping不通,则表示网络状态ERROR:

/*
	使用ping 命令源码判断网络状态是否OK
*/
#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;
}

 

相关标签: 嵌入式开发