歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
您现在的位置: Linux教程網 >> UnixLinux >  >> Linux編程 >> Linux編程

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. }  

總的說來,這個程序還是有很多很多需要修改的地方,健壯性很差,等有時間再好好完善一下.

Copyright © Linux教程網 All Rights Reserved