生活随笔
收集整理的這篇文章主要介紹了
Linux用ICMP协议实现简单Ping网络监测功能
小編覺得挺不錯的,現在分享給大家,幫大家做個參考.
From:?http://www.linuxidc.com/Linux/2012-05/61073.htm
ICMP是(Internet Control Message Protocol)Internet控制報文協議。它是TCP/IP協議族的一個子協議,用于在IP主機、路由器之間傳遞控制消息。控制消息是指網絡通不通、主機是否可達、路由是否可用等網絡本身的消息。這些控制消息雖然并不傳輸用戶數據,但是對于用戶數據的傳遞起著重要的作用。
ICMP協議是一種面向無連接的協議,用于傳輸出錯報告控制信息。它是一個非常重要的協議,它對于網絡安全具有極其重要的意義。
折騰半天,原來ICMP也是TCP/IP其中一種協議.那么監測網絡是否ping的通,就跟TCP協議差不多了。
步驟簡單歸納為:1.綁定套接字,2.發送數據包 3.接收數據包 4.解析數據包 #include?<stdio.h>? ??#include?<sys/socket.h>? ??#include?<netinet/in.h>? ??#include?<netinet/ip.h>? ??#include?<netinet/ip_icmp.h>? ??#include?<netdb.h> ?? ?
#define?PACKET_SIZE?????4096? ??#define?ERROR???????????0? ??#define?SUCCESS?????????1? ???? ?? unsigned?short ?cal_chksum(unsigned?short ?*addr,?int ?len)?? {?? ????int ?nleft=len;?? ????int ?sum=0;?? ????unsigned?short ?*w=addr;?? ????unsigned?short ?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;?? }?? ?? int ?ping(?char ?*ips,?int ?timeout)????{???????? ????struct ?timeval?*tval;?????????? ????int ?maxfds?=?0;???? ????fd_set?readfds;???? ?????? ????struct ?sockaddr_in?addr;???? ????struct ?sockaddr_in?from;???? ?????? ????bzero(&addr,sizeof (addr));???? ????addr.sin_family?=?AF_INET;???? ????addr.sin_addr.s_addr?=?inet_addr(ips);???? ?????? ????int ?sockfd;???? ?????? ????sockfd?=?socket(AF_INET,?SOCK_RAW,?IPPROTO_ICMP);???? ????if ?(sockfd?<?0)???? ????{???? ????????printf("ip:%s,socket?error\n" ,ips);???? ????????return ?ERROR;???? ????}???? ?????? ????struct ?timeval?timeo;???? ?????? ????timeo.tv_sec?=?timeout?/?1000;???? ????timeo.tv_usec?=?timeout?%?1000;???? ?????? ????if ?(setsockopt(sockfd,?SOL_SOCKET,?SO_SNDTIMEO,?&timeo,?sizeof (timeo))?==?-1)???? ????{???? ????????printf("ip:%s,setsockopt?error\n" ,ips);???? ????????return ?ERROR;???? ????}???? ?????? ????char ?sendpacket[PACKET_SIZE];???? ????char ?recvpacket[PACKET_SIZE];???? ?????? ????memset(sendpacket,?0,?sizeof (sendpacket));???? ?????? ????pid_t?pid;???? ?????? ????pid=getpid();???? ?????? ????struct ?ip?*iph;???? ????struct ?icmp?*icmp;???? ?????? ???? ????icmp=(struct ?icmp*)sendpacket;???? ????icmp->icmp_type=ICMP_ECHO;???? ????icmp->icmp_code=0;???? ????icmp->icmp_cksum=0;???? ????icmp->icmp_seq=0;???? ????icmp->icmp_id=pid;??? ????tval=?(struct ?timeval?*)icmp->icmp_data;???? ????gettimeofday(tval,NULL);???? ????icmp->icmp_cksum=cal_chksum((unsigned?short ?*)icmp,sizeof (struct ?icmp));???? ?????? ????int ?n;???? ?????? ????n?=?sendto(sockfd,?(char ?*)&sendpacket,?sizeof (struct ?icmp),?0,?(struct ?sockaddr?*)&addr,?sizeof (addr));???? ????if ?(n?<?1)???? ????{???? ????????printf("ip:%s,sendto?error\n" ,ips);???? ????????return ?ERROR;???? ????}???? ?????? ?????? ?????? ????while (1)???? ????{???? ?????????? ????????FD_ZERO(&readfds);???? ????????FD_SET(sockfd,?&readfds);???? ????????maxfds?=?sockfd?+?1;???? ????????n?=?select(maxfds,?&readfds,?NULL,?NULL,?&timeo);???? ????????if ?(n?<=?0)???? ????????{???? ????????????printf("ip:%s,Time?out?error\n" ,ips);???? ????????????close(sockfd);???? ????????????return ?ERROR;???? ????????}???? ?????????? ?????????? ????????memset(recvpacket,?0,?sizeof (recvpacket));???? ????????int ?fromlen?=?sizeof (from);???? ????????n?=?recvfrom(sockfd,?recvpacket,?sizeof (recvpacket),?0,?(struct ?sockaddr?*)&from,?(socklen_t?*)&fromlen);???? ????????if ?(n?<?1)?{???? ????????????break ;???? ????????}???? ?????????? ??????? ????????char ?*from_ip?=?(char ?*)inet_ntoa(from.sin_addr);???? ?????????????? ????????if ?(strcmp(from_ip,ips)?!=?0)???? ????????{???? ????????????printf("NowPingip:%s?Fromip:%s\nNowPingip?is?not?same?to?Fromip,so?ping?wrong!\n" ,ips,from_ip);???? ????????????return ?ERROR;?? ????????}???? ?????????? ????????iph?=?(struct ?ip?*)recvpacket;???? ?????????? ????????icmp=(struct ?icmp?*)(recvpacket?+?(iph->ip_hl<<2));???? ?????????? ????????printf("ip:%s\n,icmp->icmp_type:%d\n,icmp->icmp_id:%d\n" ,ips,icmp->icmp_type,icmp->icmp_id);???? ?????????? ????????if ?(icmp->icmp_type?==?ICMP_ECHOREPLY?&&?icmp->icmp_id?==?pid)????? ????????{???? ?????????????? ????????????break ;???? ????????}???? ????????else ???? ????????{???? ?????????????? ????????????continue ;???? ????????}???? ????}???? ?????? ????int ?main()?? {?? ????char ?cPing[16];?? ????printf("Please?input?ping?IP:" );?? ????scanf("%s" ,cPing);?? ?????? ????if (ping(cPing,10000))?? ????{?? ????????printf("Ping?succeed!\n" );?? ????}?? ????else ?? ????{?? ????????printf("Ping?wrong!\n" );?? ????}?? ?????? }?? 測試結果:
root@an-virtual-machine:~/wyz/test# ./testping Please input ping IP:192.168.1.155 Nowip:192.168.1.155 Fromip:192.168.1.133 Nowip is not same to Fromip,so ping wrong! Ping wrong! root@an-virtual-machine:~/wyz/test# ./testping Please input ping IP:192.168.1.188 ip:192.168.1.188 ,icmp->icmp_type:0 ,icmp->icmp_id:27865 Ping succeed!
總結
以上是生活随笔 為你收集整理的Linux用ICMP协议实现简单Ping网络监测功能 的全部內容,希望文章能夠幫你解決所遇到的問題。
如果覺得生活随笔 網站內容還不錯,歡迎將生活随笔 推薦給好友。