您的位置:首页 > 其它

个人简单ping程序学习及实现

2016-04-09 16:08 337 查看

1.什么是ping程序 PING程序是测试网络连接,返回网络信息的一个工具,能返回往返时间、途径路由器数量等参数

2.PING使用的协议

PING用ICMP报文协议

3.什么是原始套接字

原始套接字能直接对ip数据包进行操作,能支持icmp,igmp等协议,还可以在开启IP_HDRINCL套接字选项下对IP首部进行构造在创建套接字是套接字类型指定SOCK_RAW即可创建原始套接字。

4.PING程序的网络模型

PING程序网络模型想过当于客户/服务器网络模型,ping程序相当于客户程序,不停发送请求,循环等待接受回复消息,然后处理输出到客户端,ping的地址相当于服务器,接受消息发回icmp应答报文。

5.PING程序运行流程

1.创建原始套接字2.设置时钟信号处理程序,每次接受到信号就发送ICMP报文,时钟程序每过1秒,发出SIGALARM信号3.等待接受ICMP应答报文,处理报文,输出TTL,RTT等信息

6.总结思考

是否可以利用其他协议实现PING程序,一些服务器对ping请求直接忽略,可否利用TCP/UDP协议实现类似功能参考程序hping。

附上linux下源码

#include "unp.h"#include <netinet/in_systm.h>#include <netinet/ip.h>#include <netinet/ip_icmp.h>#define BUFSIZE 1500char *host;pid_t pid;int sockfd;int nsent;int datalen=56;char sendbuf[BUFSIZE];struct sockaddr *sasend;struct addrinfo *ai;uint16_tin_cksum(uint16_t *add, int len){int nleft = len;uint32_t sum = 0;uint16_t *w = add;uint16_t answer = 0;while (nleft > 1){sum += *w++;nleft -= 2;}if ( nleft == 1){*(unsigned char *)(&answer) = *(unsigned char *)w;sum+=answer;}sum = (sum >> 16) + (sum & 0xffff);sum += (sum >> 16);answer = ~sum;return (answer);err_quit("cksum");}voidsend_a(){int m;int len;struct icmp *icmp;icmp = (struct icmp *) sendbuf;icmp->icmp_type = ICMP_ECHO;icmp->icmp_code = 0;icmp->icmp_id = pid;icmp->icmp_seq = nsent++;memset(icmp->icmp_data, 0xa5, datalen);gettimeofday((struct timeval *) icmp->icmp_data, NULL);len = 8 + datalen;icmp->icmp_cksum = 0;icmp->icmp_cksum = in_cksum((u_short *) icmp, len);if((m=sendto(sockfd, sendbuf, len, 0, ai->ai_addr, ai->ai_addrlen))== -1)err_quit("sendto error");}voidtv_sub(struct timeval *out, struct timeval *in){if ( (out->tv_usec -= in->tv_usec ) < 0){--out->tv_sec;out->tv_usec +=1000000;}out->tv_sec -= in ->tv_sec;}voidproc(char *ptr, ssize_t len, struct msghdr *msg, struct timeval *tvrecv){int hlenl, icmplen;double rtt;struct ip *ip;struct icmp *icmp;struct timeval *tvsend;ip = (struct ip *) ptr;hlenl = (ip->ip_hl << 2);if (ip->ip_p != IPPROTO_ICMP)return;icmp = (struct icmp *)(ptr + hlenl);if ( (icmplen =len -hlenl) < 8)return ;if (icmp->icmp_type == ICMP_ECHOREPLY) {if (icmp->icmp_id != pid)return;if(icmplen < 16)return;tvsend = (struct timeval *) icmp->icmp_data;tv_sub(tvrecv, tvsend);rtt = tvrecv->tv_sec * 1000.0 + tvrecv->tv_usec/1000.0;printf("%d bytes from %s: seq=%u,ttl=%d, rtt=%.3f ms\n",icmplen, host,icmp->icmp_seq, ip->ip_ttl,rtt);}}voidsig_alrm(int signo){send_a();alarm(1);return;}voidreadloop(){int size;char recvbuf[BUFSIZE];char controlbuf[BUFSIZE];struct iovec iov;struct msghdr msg;struct timeval tval;ssize_t nn;sockfd = socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);setuid(getuid());size=60 * 1024;setsockopt(sockfd, SOL_SOCKET, SO_RCVBUF, &size,sizeof(size));sig_alrm(SIGALRM);iov.iov_base = recvbuf;iov.iov_len = sizeof(recvbuf);msg.msg_name = calloc(1,ai->ai_addrlen);msg.msg_iov = &iov;msg.msg_iovlen = 1;msg.msg_control = controlbuf;for ( ; ; ){msg.msg_namelen = ai->ai_addrlen;msg.msg_controllen = sizeof(controlbuf);nn = recvmsg (sockfd, &msg, 0);if (nn < 0){if (errno == EINTR)continue;elseerr_sys("recvmsg error");}gettimeofday(&tval, NULL);proc(recvbuf, nn, &msg, &tval);}}intmain(int argc, char **argv){ssize_t n;struct addrinfo *res;if (argc!=2)err_quit("argument not enougth");host = argv[1];pid = getpid() & 0xffff;signal(SIGALRM,sig_alrm);if (n = getaddrinfo(host,NULL,0,&res) != 0)return 0;ai = host_serv(host,NULL,0,0);readloop();exit(0);}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: