linux下ping的C語言實現

2021-09-06 01:55:28 字數 4789 閱讀 1111

#include 

<

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...