ping的简单原代码

ping的原理很简单,根据ICMP协议的特性就可以做出来。linux的头文件中包含了相应的信息。这里我就不多数了,相关的协议知识,请看相关文档。下面是我自己写的简单ping代码。
#include <signal.h>
#include <stdio.h>
#include <stdlib.h>
#include <sys/socket.h>
#include <sys/types.h>
#include <netinet/in.h>
#include <netinet/ip.h>
#include <netinet/ip_icmp.h>
#include <netdb.h>
#include <ctype.h>
#include <arpa/inet.h>
#include <unistd.h>
#include <string.h>
#include <sys/types.h>
#include <unistd.h>
#include <fcntl.h>
#define DATALEN     40
#define MAXBUFLEN   1024
#define DEFAULTPORT 8888
unsigned short in_chksum (u_short *addr, int len)
{
    register int nleft = len;
    register int sum = 0;
    u_short answer = 0;
    while (nleft > 1)
    {
        sum += *addr++;
        nleft -= 2;
    }
    if (nleft == 1)
    {
        *(u_char *)(&answer) = *(u_char *)addr;
         sum += answer;
    }
    sum = (sum >> 16) + (sum + 0xffff);
    sum += (sum >> 16);
    answer = ~sum;
    return(answer);

int main(int argc,    char** argv)  
{  
    struct sockaddr_in address,fromaddress;  
        struct in_addr inaddr;  
        struct hostent * host;  
        int sock ;      
        char host_name[256],*ifbuf;
    char buf[MAXBUFLEN];
        int i, len,fromlen,passtime;
    int timeout = 1000 ;
        struct icmp *icmpdata;
        struct timeval newtime,sendtime;  
    gethostname(host_name,MAXBUFLEN);
        host = gethostbyname(host_name);
        if (host)
        {
                i=0;
                while (host->h_addr_list[i])
                {
                        memcpy(&inaddr, host->h_addr_list[i],sizeof(address.sin_addr));      
                        printf("local ip: %s/n",inet_ntoa(inaddr));
                        i++;
                }
        }
    if (argc != 3)
        {       
                fprintf(stderr, "%s destip [timeout(ms)]/n",argv[0]);       
                fprintf(stderr, "only 1 or 2 argument is supported/n");       
                return 1;  
        }  
        host = gethostbyname(argv[1]);  
        if (argc > 2)
    {
        timeout = atoi(argv[2]);
    }
    if (timeout<10)
    {
        timeout=10;  
    }
        if (!host)
        {       
                printf("error looking up host %s/n",argv[1]);
        exit(1);  
        }  
        if ((sock = socket(AF_INET, SOCK_RAW, IPPROTO_ICMP)) < 0)
    {      
            perror("socket");
        exit(0);
        }
    if(fcntl(sock, F_SETFL, O_NONBLOCK) == -1)
        {
                perror("ioctl FIONBIO");
        }
        if (setsockopt(sock, SOL_SOCKET,SO_SNDBUF,(char*)&timeout,sizeof(timeout))<0)
        {
                perror("setsockopt SO_SNDBUF");
        }
    if (setsockopt(sock, SOL_SOCKET,SO_RCVBUF,(char*)&timeout,sizeof(timeout))<0)
    {
                perror("setsockopt SO_RCVBUF");
        }  
        address.sin_family = AF_INET;  
        memcpy(&address.sin_addr, host->h_addr_list[0],sizeof(address.sin_addr));      
        icmpdata = (struct icmp*)buf;
        memset(buf,0,sizeof(buf));
    icmpdata->icmp_type = ICMP_ECHO;
        icmpdata->icmp_code = 0;
        icmpdata->icmp_id = 0;
        icmpdata->icmp_seq = 0;
        gettimeofday((struct timeval*)&sendtime,NULL);
        len = 8+DATALEN;
        icmpdata->icmp_cksum = 0;
        icmpdata->icmp_cksum =in_chksum((unsigned short *)icmpdata,len);
        sendto(sock,buf,len,0,(struct sockaddr *) &address,sizeof(struct sockaddr_in));
        while (1)
        {
                len = recvfrom(sock,buf,sizeof(buf),0,(struct sockaddr *)&fromaddress,&fromlen);
                gettimeofday((struct timeval*)&newtime,NULL);
                passtime = ((newtime.tv_sec-sendtime.tv_sec)*1000+(newtime.tv_usec-sendtime.tv_usec)/1000);
                if (len<1)
                {
                        if (passtime>timeout)
                        {
                                printf("Time out %d msec/n",passtime);
                                break;
                        }
                        else
            {
                usleep(10000);
            }
                }
                else
                {
                        printf("echo back %d bytes in %d msec/n",len,passtime);
                for (i=0 ; i<len; i++)
                {
                        printf("%02X ", buf[i]&0xFF);
                        if ((i+1)%16 ==0) printf("/n");
                }
                printf("/n");
                        break;
                }
        }  
        close(sock);  
        return 0;
}
这段代码可以检测网络。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值