@rg070836rg
2017-01-09T16:50:43.000000Z
字数 2683
阅读 1388
TCP_IP
由于自己的偷懒,现在才开始补作业。
2017年1月10日0点
这个作业主要是用到icmp差错检查的知识,不是很难
/*设置ICMP报头*/int pack(int pack_no){int i,packsize;struct icmp *icmp;struct timeval *tval;icmp = (struct icmp*)sendpacket;icmp->icmp_type = ICMP_ECHO; //ICMP_ECHO类型的类型号为0icmp->icmp_code = 0;icmp->icmp_cksum = 0;icmp->icmp_seq = pack_no; //发送的数据报编号icmp->icmp_id = pid;packsize = 8 + datalen; //数据报大小为64字节tval = (struct timeval *)icmp->icmp_data;gettimeofday(tval,NULL); //记录发送时间//校验算法icmp->icmp_cksum = cal_chksum((unsigned shortshort *)icmp,packsize);return packsize;}
void 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");}}}
void 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++;}}
int unpack(charchar *buf,int len){int i;int iphdrlen; //ip头长度struct ip *ip;struct icmp *icmp;struct timeval *tvsend;double rtt;ip = (struct ip *)buf;iphdrlen = ip->ip_hl << 2; //求IP报文头长度,即IP报头长度乘4icmp = (struct icmp *)(buf + iphdrlen); //越过IP头,指向ICMP报头len -= iphdrlen; //ICMP报头及数据报的总长度if(len < 8) //小于ICMP报头的长度则不合理{printf("ICMP packet\'s length is less than 8\n");return -1;}//确保所接收的是所发的ICMP的回应if((icmp->icmp_type == ICMP_ECHOREPLY) && (icmp->icmp_id == pid)){tvsend = (struct timeval *)icmp->icmp_data;tv_sub(&tvrecv,tvsend); //接收和发送的时间差//以毫秒为单位计算rttrtt = tvrecv.tv_sec*1000 + tvrecv.tv_usec/1000;temp_rtt[nreceived] = rtt;all_time += rtt; //总时间//显示相关的信息printf("%d bytes from %s: icmp_seq=%u ttl=%d time=%.1f ms\n",len,inet_ntoa(from.sin_addr),icmp->icmp_seq,ip->ip_ttl,rtt);}else return -1;}
生成ICMP的原始套接字,压入ip,发包,守包,检查包内内容,然后设置ttl
main(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(网络套接字)//压入ipdest_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;}
