C语言实现MAC帧的封装与解封装


这周做计算机网络课程设计,在几个题目中选了个MAC帧的封装.

首先看最后结果:




这里有个bug,不知道为什么帧前导码和帧定界符前多了FFFFFF,我自己没搞懂???

程序如下:

  1. /* 
  2. 目标: 
  3. 封装 
  4. 1.将inputFile文件中的数据封装成MAC帧,封装好的MAC帧写入outputFile文件中. 
  5. 2.如果数据长度小于46字节,则补全到46字节 
  6. 3.如果数据长度大于1500,则封装成多个MAC帧 
  7. 解封装: 
  8. 读取outputFile中的数据,并逐个显示帧的信息 
  9.  
  10. 其实我们要求还是蛮低的,上面有好多是自己添加的 
  11. */  
  12. #include <stdio.h>   
  13. #include <stdlib.h>   
  14. #define MAXSIZE 1500   
  15. #define echo(format,str) printf("%"#format,str)   
  16. #define inputFile "inputFile.txt"    
  17. #define outputFile "outputFile.txt"    
  18. void flush()  
  19. {  
  20.     fflush(stdin);  
  21.     fflush(stdout);  
  22. }  
  23.   
  24.   
  25. unsigned int  crc8(unsigned char *ptr,unsigned  int len)  
  26. /* 
  27. CRC校验,ptr是需要计算的数组首地址,len是需要计算的长度 
  28. */  
  29. {  
  30.     unsigned int  CRC = 0;  
  31.     unsigned int  i;  
  32.       
  33.     while(len--){  
  34.         CRC = CRC^ *ptr++;  
  35.         for(i = 0; i < 8; i++){  
  36.             if(CRC & 0x01){  
  37.                 CRC = (CRC >> 1 )^ 0x8c;  
  38.             }  
  39.             else{  
  40.                 CRC >>= 1;  
  41.             }  
  42.         }                     
  43.     }  
  44.       
  45.     return CRC;    
  46. }  
  47.   
  48.   
  49. int encapsulation()  
  50. /*帧封装函数*/  
  51. {  
  52.     int i,dataCrc,nu,j,lastNu,sum;  
  53.     FILE *fpIn,*fpOut;  
  54.     int src[6],des[6];  
  55.     char type[2],data[MAXSIZE];  
  56.     if((fpIn=fopen(inputFile,"a+"))==NULL)  
  57.     {  
  58.         echo(s,"打开文件失败!");  
  59.         return 1;  
  60.     }  
  61.     if((fpOut=fopen(outputFile,"wb"))==NULL)  
  62.     {  
  63.         echo(s,"写入文件失败");  
  64.         return 1;  
  65.     }  
  66.   
  67.     fseek(fpIn,0,SEEK_END);  
  68.     sum=ftell(fpIn);  
  69.     nu=sum/1500;  
  70.     if((sum-nu*1500)<46)  
  71.     {  
  72.         for(i=0;i<(46-(sum-nu*1500));i++)  
  73.             fputc(0x0,fpIn);   //如果不足,则填充   
  74.     }  
  75.   
  76.     rewind(fpIn);  
  77.   
  78.     echo(s,"请输源MAC:");  
  79.     scanf("%x-%x-%x-%x-%x-%x",src,src+1,src+2,src+3,src+4,src+5);  
  80.     fflush(stdin);  
  81.     echo(s,"请输入目标MAC:");  
  82.     scanf("%x-%x-%x-%x-%x-%x",des,des+1,des+2,des+3,des+4,des+5);  
  83.     flush();  
  84.     echo(s,"请输入类型字段:");  
  85.     flush();  
  86.     scanf("%2x%2x",type,type+1);  
  87.   
  88.     for(j=0;j<nu+1;j++)  
  89.     {  
  90.         for(i=0;i<7;i++)  
  91.             fputc(0xaa,fpOut);   //写入帧前导码   
  92.         fputc(0xab,fpOut);       //写入帧定界符   
  93.   
  94.         for(i=0;i<6;i++)  
  95.         {  
  96.             fputc(des[i],fpOut);    //写入目的MAC   
  97.         }  
  98.         for(i=0;i<6;i++)  
  99.         {  
  100.             fputc(src[i],fpOut);   //写入源MAC   
  101.         }  
  102.           
  103.         fputc(type[0],fpOut);     //写入类型号   
  104.         fputc(type[1],fpOut);  
  105.   
  106.   
  107.         if(j!=nu)  
  108.         /*不是最后一个数据,则前面的数据都应该是1500*/  
  109.         {  
  110.             fread(data,sizeof(char),1500,fpIn);  
  111.             fwrite(data,sizeof(char),1500,fpOut);  
  112.             dataCrc=crc8(data,1500);  
  113.             fputc(dataCrc,fpOut);  
  114.         }  
  115.         else  
  116.         {  
  117.             //最后一段数据,需要额外处理,获取长度   
  118.             lastNu=ftell(fpIn);  
  119.             fread(data,sizeof(char),sum-lastNu,fpIn);  
  120.             fwrite(data,sizeof(char),sum-lastNu,fpOut);  
  121.             dataCrc=crc8(data,sum-lastNu);  
  122.             fputc(dataCrc,fpOut);  
  123.         }  
  124.     }  
  125.       
  126.     fclose(fpIn);  
  127.     fclose(fpOut);  
  128.   
  129.     echo(s,"\n\n");  
  130.   
  131.     return 0;  
  132. }  
  133.   
  134.   
  135. int unPack()  
  136. /*解封装函数*/  
  137. {     
  138.     int i,dataStart,dataEnd,srcCrc,nowCrc,dataLength,frameNu=0,sum,j;  
  139.     char c,data[MAXSIZE];  
  140.     FILE *fpOut;  
  141.     if((fpOut=fopen(outputFile,"rb"))==NULL)  
  142.     {  
  143.         echo(s,"打开文件失败!");  
  144.         return 1;  
  145.     }  
  146.   
  147.     fseek(fpOut,0,SEEK_END);  
  148.     sum=ftell(fpOut);  
  149.     rewind(fpOut);  
  150.   
  151.     while(1)  
  152.         /*此循环为了获取帧的个数 
  153.         主要思路:连续7个0xaa,第8个是0xab 
  154.         */  
  155.     {  
  156.         if(ftell(fpOut)>=sum)  
  157.         {  
  158.             break;  
  159.         }  
  160.         for(i=0;i<7;i++)  
  161.         {  
  162.             if(ftell(fpOut)>=sum)  
  163.             {  
  164.                 break;  
  165.             }  
  166.   
  167.             if(fgetc(fpOut)!=0xaa)  
  168.             {  
  169.                 i=-1;  
  170.             }  
  171.         }  
  172.         if(ftell(fpOut)>=sum)  
  173.         {  
  174.             break;  
  175.         }  
  176.         if(fgetc(fpOut)==0xab)  
  177.         {  
  178.             ++frameNu;  
  179.         }  
  180.     }  
  181.     rewind(fpOut);  
  182.   
  183.     for(j=0;j<frameNu;j++)  
  184.         /*循环逐个输出帧的信息*/  
  185.     {  
  186.         printf("\n\n帧序号: %d\n\n",j+1);  
  187.         echo(s,"帧前导码: ");  
  188.         for (i=0;i<7;i++)  
  189.         {  
  190.             c=fgetc(fpOut);  
  191.             echo(.2X,c);  
  192.         }  
  193.         echo(s,"\n\n");  
  194.   
  195.         echo(s,"帧前定界符: ");  
  196.         {  
  197.             c=fgetc(fpOut);  
  198.             echo(.2X,c);  
  199.         }  
  200.   
  201.         echo(s,"\n\n");  
  202.   
  203.         echo(s,"目的MAC地址: ");  
  204.         for (i=0;i<6;i++)  
  205.         {  
  206.             c=fgetc(fpOut);  
  207.             echo(.2X,c);  
  208.             if (i!=5)  
  209.                 echo(s,"-");      
  210.         }  
  211.         echo(s,"\n\n");   
  212.   
  213.         echo(s,"源MAC地址: ");  
  214.         for (i=0;i<6;i++)  
  215.         {  
  216.             c=fgetc(fpOut);  
  217.             echo(.2X,c);  
  218.             if (i!=5)  
  219.                 echo(s,"-");      
  220.         }  
  221.         echo(s,"\n\n");  
  222.   
  223.         echo(s,"类型号: ");  
  224.   
  225.         c=fgetc(fpOut);  
  226.         echo(.2X,c);  
  227.         c=fgetc(fpOut);  
  228.         echo(.2X,c);  
  229.   
  230.         if(j!=frameNu-1)  
  231.             //不是最后一个帧,则数据长度都是1500   
  232.         {  
  233.             fread(data,sizeof(char),1500,fpOut);  
  234.             srcCrc=fgetc(fpOut);  
  235.             nowCrc=crc8(data,1500);  
  236.         }  
  237.         else  
  238.         {  
  239.             //最后一个帧,额外处理   
  240.             dataStart=ftell(fpOut);  
  241.             fseek(fpOut,-1,SEEK_END);  
  242.             dataEnd=ftell(fpOut)-1;  
  243.             dataLength=dataEnd-dataStart+1;  
  244.             srcCrc=fgetc(fpOut);  
  245.             fseek(fpOut,dataStart,SEEK_SET);  
  246.             fread(data,sizeof(char),dataLength,fpOut);  
  247.             nowCrc=crc8(data,dataLength);  
  248.         }  
  249.   
  250.         printf("\n\n本次CRC:  %d",nowCrc);  
  251.         echo(s,"\n\n行为: ");  
  252.         if (nowCrc==srcCrc) //比较CRC,是否出错   
  253.             echo(s,"接受");  
  254.         else  
  255.             echo(s,"丢弃");  
  256.             printf("  前次CRC:%d",srcCrc);  
  257.       
  258.     }  
  259.     fclose(fpOut);  
  260.     echo(s,"\n\n");  
  261.     return 0;  
  262. }  
  263. void choice()  
  264. {  
  265.     int choice;  
  266.     echo(s,"1.帧封装\n");  
  267.     echo(s,"2.帧解析\n");  
  268.     echo(s,"3.退出\n");  
  269.     echo(s,"\t请选择序号:");  
  270.     scanf("%d",&choice);  
  271.     switch(choice)  
  272.     {  
  273.     case 1:  
  274.         encapsulation();  
  275.         break;  
  276.     case 2:  
  277.         unPack();  
  278.         break;  
  279.     case 3:  
  280.         echo(s,"欢迎使用....\n");  
  281.         exit(0);  
  282.     default:  
  283.         putchar('\a');  
  284.         echo(s,"序号在1-3,请重新选择\n");  
  285.               
  286.     }  
  287. }  
  288. int main(int argc,char **argv)  
  289. {  
  290.     while(1)  
  291.     {  
  292.           
  293.         choice();  
  294.         echo(s,"\n");  
  295.     }  
  296.     return 0;  
  297.       
  298. }  

总的说来,这个程序还是有很多很多需要修改的地方,健壮性很差,等有时间再好好完善一下.

相关内容