<
stdio.h
>
#include
<
signal.h
>
#include
<
arpa
/inet.h
>
#include
<
sys/
types.h
>
#include
<
sys/
socket.h
>
#include
<
unistd.h
>
#include
<
netinet/in
.h>
#include
<
netinet
/ip.h
>
#include
<
netinet
/ip_icmp.h
>
#include
<
netdb.h
>
#include
<
setjmp.h
>
#include
<
errno.h
>
#define
packet_size 4096
#define
max_wait_time 5
#define
max_no_packets 3
char
sendpacket[packet_size];
char
recvpacket[packet_size];
intsockfd,datalen=56
;int
nsend=0
,nreceived=0
;struct
sockaddr_in dest_addr;
pid_t pid;
struct
sockaddr_in from;
struct
timeval tvrecv;
void
statistics(
intsigno);
unsigned
short
cal_chksum(unsigned
short
*addr,
intlen);
intpack(
intpack_no);
void
send_packet(
void
);void
recv_packet(
void
);int
unpack(
char
*buf,
intlen);
void
tv_sub(
struct
timeval
*out
,struct
timeval *in
);void
statistics(
intsigno)
/*校驗和演算法
*/unsigned
short
cal_chksum(unsigned
short
*addr,
intlen)
/*若icmp報頭為奇數個位元組,會剩下最後一位元組。把最後乙個位元組視為乙個2位元組資料的高位元組,這個2位元組資料的低位元組為0,繼續累加
*/if
( nleft==1
)sum
=(sum
>>16)
+(sum
&0xffff
);sum
+=(sum
>>
16);
answer
=~sum;
return
answer;}/*
設定icmp報頭
*/int
pack(
intpack_no)
/*傳送三個icmp報文
*/void
send_packet()
sleep(
1);
/*每隔一秒傳送乙個icmp報文*/}
}/*接收所有icmp報文
*/void
recv_packet()
gettimeofday(
&tvrecv,null);
/*記錄接收時間
*/if
(unpack(recvpacket,n)
==-1
)continue
;nreceived++;
}}/*剝去icmp報頭
*/int
unpack(
char
*buf,
intlen)
/*確保所接收的是我所發的的icmp的回應
*/if
( (icmp
->
icmp_type
==icmp_echoreply)
&&(icmp
->
icmp_id
==pid) )
else
return-1
;}main(
intargc,
char
*argv)
if( (protocol
=getprotobyname(
"icmp
") )
==null)
/*生成使用icmp的原始套接字,這種套接字只有root才能生成
*/if
( (sockfd
=socket(af_inet,sock_raw,protocol
->
p_proto) )
<0)
/***root許可權,設定當前使用者許可權
*/setuid(getuid());
/*擴大套接字接收緩衝區到50k這樣做主要為了減小接收緩衝區溢位的
的可能性,若無意中ping乙個廣播位址或多播位址,將會引來大量應答
*/setsockopt(sockfd,sol_socket,so_rcvbuf,
&size,
sizeof
(size) );
bzero(
&dest_addr,
sizeof
(dest_addr));
dest_addr.sin_family
=af_inet;
/*判斷是主機名還是ip位址
*/if
( inaddr
=inet_addr(argv[1])
==inaddr_none)
memcpy( (
char*)
&dest_addr.sin_addr,host
->
h_addr,host
->
h_length);
}else
/*是ip位址
*/memcpy( (
char*)
&dest_addr,(
char*)
&inaddr,host
->
h_length);
/*獲取main的程序id,用於設定icmp的標誌符
*/pid
=getpid();
printf(
"ping %s(%s): %d bytes data in icmp packets.\n
",argv[1],
inet_ntoa(dest_addr.sin_addr),datalen);
send_packet();
/*傳送所有icmp報文
*/recv_packet();
/*接收所有icmp報文
*/statistics(sigalrm);
/*進行統計
*/return0;
}/*兩個timeval結構相減
*/void
tv_sub(
struct
timeval
*out
,struct
timeval *in
)out
->
tv_sec
-=in
->
tv_sec;}/*
------------- the end -----------*/
仍然需要注意許可權的問題,按照如下方式編譯:
sudo gcc myping.c -o myping
sudo chmod u+s myping
./myping www.163.com
執行顯示結果:
ping www.cn.ibm.com(121.195.178.238): 56 bytes data in icmp packets.
64 byte from 121.195.178.238: icmp_seq=1 ttl=242 rtt=3029.000 ms
64 byte from 121.195.178.238: icmp_seq=2 ttl=242 rtt=2020.000 ms
64 byte from 121.195.178.238: icmp_seq=3 ttl=242 rtt=1010.000 ms
--------------------ping statistics-------------------
3 packets transmitted, 3 received , %0 lost
C語言實現ping命令(一)
ping命令使用到了網路中的icmp協議 關於icmp介紹看這裡 網路位址資訊 struct sockaddr in struct in addr struct in addr define in addr t uint32 t 無符號整型32位 還可以使用以下結構體 struct sockaddr...
Linux下C語言實現CopyFile
linux下c語言實現檔案拷貝 function copy file from file1 to file2 how to execute copyfile file1 file2 under linux data 2007 05 09 include fprintf stderr,bufsiz i...
Linux下C語言實現UDP Socket程式設計
該博文參考了linux c socket 程式設計之udp一文,在這裡表示感謝!傳送方 file udp sender.c author henry created on 2019年5月29日17 08 13 主要實現 傳送20個文字訊息,然後再傳送乙個終止訊息 include include in...