wolflion
ping的源代码
http://blog.chinaunix.net/u1/48325/showart.php?id=719303
【
用C语言实现Ping程序功能
】
http://blog.chinaunix.net/u1/48325/showart_719319.html
【Linux下Ping的实现代码】
以下为ping的伪代码
1
#define
PACKET_SIZE 4096
2
#define
MAX_WAIT_TIME 5
3
4
char
sendpacket[PACKET_SIZE];
5
char
recvpacket[PACKET_SIZE];
6
int
sockfd,datalen
=
56
;
7
int
nsend
=
0
,nreceived
=
0
;
8
struct
sockaddr_in dest_addr;
9
pid_t pid;
10
struct
sockaddr
in
from;
11
struct
timeval tvrecv;
12
13
void
statistics()
14
{
15
printf(
.);
//
打印统计信息
16
close(sockfd);
17
exit(
1
);
18
}
19
20
//
校验和算法
21
unsigned
short
cal chksum(unsigned
short
*
addr,
int
len)
22
{
23
.
24
}
25
26
//
设置ICMP报头
27
int
pack(
int
pack_no)
28
{
29
int
i,packsize;
30
struct
icmp
*
icmp;
31
struct
timeval
*
tval;
32
33
icmp
=
(
struct
icmp
*
)sendpacket;
34
icmp
->
icmp_type
=
ICMP_ECHO;
35
icmp
->
icmp_code
=
0
;
36
icmp
->
icmp_cksum
=
0
;
37
icmp
->
icmp_seq
=
pack_no;
38
icmp
->
icmp_id
=
pid;
39
40
packsize
=
8
+
datalen;
41
tval
=
(
struct
timeval
*
)icmp
->
icmp_data;
42
gettimeofday(tval,NULL);
//
记录发送时间
43
//
校验算法
44
icmp
->
icmp_cksum
=
cal_chksum((unsigned
short
*
)icmp,packsize);
45
return
packsize;
46
}
47
48
49
//
发送三个ICMP报文
50
void
send_packet()
51
{
52
int
packetsize;
53
while
(nsend
<
3
)
54
{
55
nsend
++
;
56
packetsize
=
pack(nsend);
//
设置ICMP报头
57
sendto(sockfd,sendpacket,packetsize,
0
,(
struct
sockaddr
*
)
&
dest_addr,
sizeof
(dest_addr));
58
sleep(
1
);
//
每隔一秒发送一个ICMP报文
59
}
60
}
61
62
//
接收所有ICMP报文
63
void
recv_packet()
64
{
65
int
n,fromlen;
66
while
(nreceived
<
nsend)
67
{
68
alarm(MAX_WAIT_TIME);
69
recvfrom(sockfd,recvpacket,
sizeof
(recvpacket),
0
,(
struct
sockaddr
*
)
&
from,
&
fromlen);
//
显示相关信息
70
gettimeofday(
&
tvrecv,NULL);
//
记录接收时间
71
unpack(recvpacket,n);
//
对该ICMP报文进行解析
72
nreceived
++
;
73
}
74
}
75
76
//
剥去ICMP报头
77
int
unpack(
char
*
buf,
int
len)
78
{
79
int
i,iphdrlen;
80
struct
ip
*
ip;
81
struct
icmp
*
icmp;
82
struct
timeval
*
tvsend;
83
double
rtt;
84
85
ip
=
(
struct
ip
*
) buf;
86
iphdrlen
=
ip
->
ip_h1
<<
2
;
//
求ip报头长度,即ip报头的长度标志乘4
87
icmp
=
(
struct
icmp
*
)(buf
+
iphdrlen);
//
越过ip报头,指向ICMP报头
88
len
-=
iphdrlen;
//
ICMP报头及ICMP数据报的总长度
89
if
(len
<
8
)
90
{
91
.
92
return
-
1
;
93
}
94
//
确保所接收的是我所发的ICMP的回应
95
if
((icmp
->
icmp_type
==
ICMP_ECHO_REPLY)
&&
(icmp
->
icmp_id
==
pid))
96
{
97
..
98
printf(
..);
//
显示相关信息
99
}
100
else
101
return
-
1
;
102
}
103
104
mian(
int
argc,
char
*
argv[])
105
{
106
unsigned
long
inaddr
=
01
;
107
int
size
=
50
*
1024
;
108
109
//
生成使用ICMP的原始套接字,其protocol是17
110
sockfd
=
socket(AF_INET,SOCK_RAW,IPPROTO_ICMP);
111
112
//
扩大套接字接收缓冲区到50K这样做主要为了减小接收缓冲区溢出的
113
//
可能性,若无意中ping一个广播地址或多播地址,将会引起大量应答
114
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,
&
size,
sizeof
(size));
115
bzero(
&
dest_addr,
sizeof
(dest_addr));
116
dest_addr.sin_family
=
AF_INET;
117
118
send_packet();
//
发送所有ICMP报文
119
recv_packet();
//
接收所有ICMP报文
120
statistics();
//
进行统计
121
122
return
0
;
123
}
posted on 2009-12-29 14:20
lionel
阅读(408)
评论(0)
编辑
收藏
引用
只有注册用户
登录
后才能发表评论。
网站导航:
博客园
博客园最新博文
博问
管理
My Links
C++博客
首页
联系
聚合
管理
Blog Stats
Posts - 1
Stories - 7
Comments - 0
Trackbacks - 0
常用链接
我的随笔
我的评论
我参与的随笔
留言簿
给我留言
查看公开留言
查看私人留言
随笔分类
数据结构(1)
(RSS)
随笔档案
2012年6月 (1)
文章分类
开源数据库(1)
(RSS)
开源协议
(RSS)
软件工程
(RSS)
文章档案
2012年1月 (1)
2010年9月 (1)
2010年4月 (1)
2010年1月 (1)
2009年12月 (3)
搜索
最新评论