发送数据时,在设置totalLen时,需要注意使用htonl函数转换得到的是4字节数据,即为unsigned类型,直接赋值给short类型会发生数据截取,导致设置totalLen时使用 short totalLen = htonl(len+20);
赋值时,得到的数据永远为0,因为截取时只能得到转换后的低16位,即原来的高16位,即0。因此需要移位或者自行设置每个字节
设置校验和时应该注意先将校验和处设置为0,计算得到的校验和取反就是需要填入相应位置的校验和。
代码
/*
* THIS FILE IS FOR IP TEST
*/// system support#include"sysInclude.h"externvoidip_DiscardPkt(char* pBuffer,int type);externvoidip_SendtoLower(char*pBuffer,int length);externvoidip_SendtoUp(char*pBuffer,int length);externunsignedintgetIpv4Address();// implemented by studentsunsignedgetCheckSum(unsignedshort* pBuffer,unsigned headLen){unsigned sum =0;int i =0;
headLen = headLen /2;while(headLen > i){
sum +=(unsigned)pBuffer[i];
i++;}if(sum &0xffff!= sum){
sum =(sum &0xffff)+(sum >>16);}return sum;}intstud_ip_recv(char*pBuffer,unsignedshort length){printf("-----recv a ipv4 packet");//检查版本号unsigned version =(pBuffer[0])>>4;printf("-----the version is %x\n", version);if(version !=4){ip_DiscardPkt(pBuffer, STUD_IP_TEST_VERSION_ERROR);return1;}//检查头部长度unsigned headLen =(unsigned)(pBuffer[0])&0xf;
headLen *=4;if(headLen <20){ip_DiscardPkt(pBuffer, STUD_IP_TEST_HEADLEN_ERROR);}//检查生存时间unsigned ttl =(unsigned)(pBuffer[8]);printf("-----the ttl is %d\n", ttl);if(ttl <=0){ip_DiscardPkt(pBuffer, STUD_IP_TEST_TTL_ERROR);return1;}//检查校验和if(getCheckSum((unsignedshort*)pBuffer, headLen)!=0xffff){ip_DiscardPkt(pBuffer, STUD_IP_TEST_CHECKSUM_ERROR);return1;}//检查接受地址unsigned localAddr =getIpv4Address();unsigned recvAddr =((unsigned*)pBuffer)[4];
recvAddr =ntohl(recvAddr);printf("-----the local addr is %d ,the recv addr is %d\n", localAddr, recvAddr);if(localAddr != recvAddr || recvAddr ==0xffffffff){ip_DiscardPkt(pBuffer, STUD_IP_TEST_DESTINATION_ERROR);return1;}//接受printf("-----accept a packet");
pBuffer += headLen;ip_SendtoUp(pBuffer, length - headLen);return0;}intstud_ip_Upsend(char*pBuffer,unsignedshort len,unsignedint srcAddr,unsignedint dstAddr, byte protocol, byte ttl){printf("-----send a packet\n");char* buffer =(char*)malloc(len +20);memcpy(buffer +20, pBuffer, len);//version,headLen,ServiceType。
buffer[0]=0x45;
buffer[1]=0x0;//totalLenunsignedshort totalLen = len +20;
buffer[3]= totalLen &0xff;
buffer[2]= totalLen >>8;printf("-----total len is %x\n", len +20);//identification((unsignedshort*)buffer)[2]=0;//flags fragment offset((unsignedshort*)buffer)[3]=0;//ttl
buffer[8]= ttl;printf("-----ttl is %x\n", ttl);//protocol
buffer[9]= protocol;printf("-----protocol is %x\n", protocol);//init header checksum((unsignedshort*)buffer)[5]=0;//source ip((unsigned*)buffer)[3]=htonl(srcAddr);//des ip((unsigned*)buffer)[4]=htonl(dstAddr);printf("-----src ip is %x,dst ip is %x\n", srcAddr, dstAddr);//update checkSUmunsignedshort checkSum =~getCheckSum((unsignedshort*)buffer,20);((unsignedshort*)buffer)[5]= checkSum;printf("-----checksum is %x\n", checkSum);//sendip_SendtoLower(buffer, len +20);return0;}