由于自己的偷懒,现在才开始补作业。
2017年1月10日0点
#第四次作业 myping
这个作业主要是用到icmp差错检查的知识,不是很难
设置ICMP报头函数,压包
1 | /*设置ICMP报头*/ |
#发送ICMP报文1
2
3
4
5
6
7
8
9
10
11
12
13
14
15void send_packet()
{
int packetsize;
if(nsend < MAX_NO_PACKETS)
{
nsend++;
packetsize = pack(nsend); //设置ICMP报头
//发送数据报
if(sendto(sockfd,sendpacket,packetsize,0,
(struct sockaddr *)&dest_addr,sizeof(dest_addr)) < 0)
{
perror("sendto error");
}
}
}
#接受ICMP报文1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18void recv_packet()
{
int n,fromlen;
extern int error;
fromlen = sizeof(from);
if(nreceived < nsend)
{
//接收数据报
if((n = recvfrom(sockfd,recvpacket,sizeof(recvpacket),0,
(struct sockaddr *)&from,&fromlen)) < 0)
{
perror("recvfrom error");
}
gettimeofday(&tvrecv,NULL); //记录接收时间
unpack(recvpacket,n); //剥去ICMP报头
nreceived++;
}
}
拆包,做时间计算等
1 | int unpack(charchar *buf,int len) |
#主调用函数
生成ICMP的原始套接字,压入ip,发包,守包,检查包内内容,然后设置ttl1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47main(int argc,charchar *argv[])
{
struct hostent *host;
struct protoent *protocol;
unsigned long inaddr = 0;
int size = 550 * 1024;
addr[0] = argv[1];
//参数小于两个
if(argc < 2)
{
printf("usage:%s hostname/IP address\n",argv[0]);
exit(1);
}
//不是ICMP协议
if((protocol = getprotobyname("icmp")) == NULL)
{
perror("getprotobyname");
exit(1);
}
//生成使用ICMP的原始套接字
if((sockfd = socket(AF_INET,SOCK_RAW,protocol->p_proto)) < 0)
{
perror("socket error");
exit(1);
}
setsockopt(sockfd,SOL_SOCKET,SO_RCVBUF,&size,sizeof(size));
bzero(&dest_addr,sizeof(dest_addr)); //初始化
dest_addr.sin_family = AF_INET; //套接字域是AF_INET(网络套接字)
//压入ip
dest_addr.sin_addr.s_addr = inet_addr(argv[1]);
pid = getpid();
printf("PING %s(%s):%d bytes of data.\n",argv[1],
inet_ntoa(dest_addr.sin_addr),datalen);
//当按下ctrl+c时发出中断信号,并开始执行统计函数
signal(SIGINT,statistics);
while(nsend < MAX_NO_PACKETS){
sleep(1); //每隔一秒发送一个ICMP报文
send_packet(); //发送ICMP报文
recv_packet(); //接收ICMP报文
}
return 0;
}