由于自己的偷懒,现在才开始补作业。
    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;  
}