歡迎來到Linux教程網
Linux教程網
Linux教程網
Linux教程網
Linux教程網 >> Linux編程 >> Linux編程 >> C語言實現MAC幀的封裝與解封裝

C語言實現MAC幀的封裝與解封裝

日期:2017/3/1 10:19:49   编辑:Linux編程

這周做計算機網絡課程設計,在幾個題目中選了個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. #include <stdio.h>
  12. #include <stdlib.h>
  13. #define MAXSIZE 1500
  14. #define echo(format,str) printf("%"#format,str)
  15. #define inputFile "inputFile.txt"
  16. #define outputFile "outputFile.txt"
  17. void flush()
  18. {
  19. fflush(stdin);
  20. fflush(stdout);
  21. }
  22. unsigned int crc8(unsigned char *ptr,unsigned int len)
  23. /*
  24. CRC校驗,ptr是需要計算的數組首地址,len是需要計算的長度
  25. */
  26. {
  27. unsigned int CRC = 0;
  28. unsigned int i;
  29. while(len--){
  30. CRC = CRC^ *ptr++;
  31. for(i = 0; i < 8; i++){
  32. if(CRC & 0x01){
  33. CRC = (CRC >> 1 )^ 0x8c;
  34. }
  35. else{
  36. CRC >>= 1;
  37. }
  38. }
  39. }
  40. return CRC;
  41. }
  42. int encapsulation()
  43. /*幀封裝函數*/
  44. {
  45. int i,dataCrc,nu,j,lastNu,sum;
  46. FILE *fpIn,*fpOut;
  47. int src[6],des[6];
  48. char type[2],data[MAXSIZE];
  49. if((fpIn=fopen(inputFile,"a+"))==NULL)
  50. {
  51. echo(s,"打開文件失敗!");
  52. return 1;
  53. }
  54. if((fpOut=fopen(outputFile,"wb"))==NULL)
  55. {
  56. echo(s,"寫入文件失敗");
  57. return 1;
  58. }
  59. fseek(fpIn,0,SEEK_END);
  60. sum=ftell(fpIn);
  61. nu=sum/1500;
  62. if((sum-nu*1500)<46)
  63. {
  64. for(i=0;i<(46-(sum-nu*1500));i++)
  65. fputc(0x0,fpIn); //如果不足,則填充
  66. }
  67. rewind(fpIn);
  68. echo(s,"請輸源MAC:");
  69. scanf("%x-%x-%x-%x-%x-%x",src,src+1,src+2,src+3,src+4,src+5);
  70. fflush(stdin);
  71. echo(s,"請輸入目標MAC:");
  72. scanf("%x-%x-%x-%x-%x-%x",des,des+1,des+2,des+3,des+4,des+5);
  73. flush();
  74. echo(s,"請輸入類型字段:");
  75. flush();
  76. scanf("%2x%2x",type,type+1);
  77. for(j=0;j<nu+1;j++)
  78. {
  79. for(i=0;i<7;i++)
  80. fputc(0xaa,fpOut); //寫入幀前導碼
  81. fputc(0xab,fpOut); //寫入幀定界符
  82. for(i=0;i<6;i++)
  83. {
  84. fputc(des[i],fpOut); //寫入目的MAC
  85. }
  86. for(i=0;i<6;i++)
  87. {
  88. fputc(src[i],fpOut); //寫入源MAC
  89. }
  90. fputc(type[0],fpOut); //寫入類型號
  91. fputc(type[1],fpOut);
  92. if(j!=nu)
  93. /*不是最後一個數據,則前面的數據都應該是1500*/
  94. {
  95. fread(data,sizeof(char),1500,fpIn);
  96. fwrite(data,sizeof(char),1500,fpOut);
  97. dataCrc=crc8(data,1500);
  98. fputc(dataCrc,fpOut);
  99. }
  100. else
  101. {
  102. //最後一段數據,需要額外處理,獲取長度
  103. lastNu=ftell(fpIn);
  104. fread(data,sizeof(char),sum-lastNu,fpIn);
  105. fwrite(data,sizeof(char),sum-lastNu,fpOut);
  106. dataCrc=crc8(data,sum-lastNu);
  107. fputc(dataCrc,fpOut);
  108. }
  109. }
  110. fclose(fpIn);
  111. fclose(fpOut);
  112. echo(s,"\n\n");
  113. return 0;
  114. }
  115. int unPack()
  116. /*解封裝函數*/
  117. {
  118. int i,dataStart,dataEnd,srcCrc,nowCrc,dataLength,frameNu=0,sum,j;
  119. char c,data[MAXSIZE];
  120. FILE *fpOut;
  121. if((fpOut=fopen(outputFile,"rb"))==NULL)
  122. {
  123. echo(s,"打開文件失敗!");
  124. return 1;
  125. }
  126. fseek(fpOut,0,SEEK_END);
  127. sum=ftell(fpOut);
  128. rewind(fpOut);
  129. while(1)
  130. /*此循環為了獲取幀的個數
  131. 主要思路:連續7個0xaa,第8個是0xab
  132. */
  133. {
  134. if(ftell(fpOut)>=sum)
  135. {
  136. break;
  137. }
  138. for(i=0;i<7;i++)
  139. {
  140. if(ftell(fpOut)>=sum)
  141. {
  142. break;
  143. }
  144. if(fgetc(fpOut)!=0xaa)
  145. {
  146. i=-1;
  147. }
  148. }
  149. if(ftell(fpOut)>=sum)
  150. {
  151. break;
  152. }
  153. if(fgetc(fpOut)==0xab)
  154. {
  155. ++frameNu;
  156. }
  157. }
  158. rewind(fpOut);
  159. for(j=0;j<frameNu;j++)
  160. /*循環逐個輸出幀的信息*/
  161. {
  162. printf("\n\n幀序號: %d\n\n",j+1);
  163. echo(s,"幀前導碼: ");
  164. for (i=0;i<7;i++)
  165. {
  166. c=fgetc(fpOut);
  167. echo(.2X,c);
  168. }
  169. echo(s,"\n\n");
  170. echo(s,"幀前定界符: ");
  171. {
  172. c=fgetc(fpOut);
  173. echo(.2X,c);
  174. }
  175. echo(s,"\n\n");
  176. echo(s,"目的MAC地址: ");
  177. for (i=0;i<6;i++)
  178. {
  179. c=fgetc(fpOut);
  180. echo(.2X,c);
  181. if (i!=5)
  182. echo(s,"-");
  183. }
  184. echo(s,"\n\n");
  185. echo(s,"源MAC地址: ");
  186. for (i=0;i<6;i++)
  187. {
  188. c=fgetc(fpOut);
  189. echo(.2X,c);
  190. if (i!=5)
  191. echo(s,"-");
  192. }
  193. echo(s,"\n\n");
  194. echo(s,"類型號: ");
  195. c=fgetc(fpOut);
  196. echo(.2X,c);
  197. c=fgetc(fpOut);
  198. echo(.2X,c);
  199. if(j!=frameNu-1)
  200. //不是最後一個幀,則數據長度都是1500
  201. {
  202. fread(data,sizeof(char),1500,fpOut);
  203. srcCrc=fgetc(fpOut);
  204. nowCrc=crc8(data,1500);
  205. }
  206. else
  207. {
  208. //最後一個幀,額外處理
  209. dataStart=ftell(fpOut);
  210. fseek(fpOut,-1,SEEK_END);
  211. dataEnd=ftell(fpOut)-1;
  212. dataLength=dataEnd-dataStart+1;
  213. srcCrc=fgetc(fpOut);
  214. fseek(fpOut,dataStart,SEEK_SET);
  215. fread(data,sizeof(char),dataLength,fpOut);
  216. nowCrc=crc8(data,dataLength);
  217. }
  218. printf("\n\n本次CRC: %d",nowCrc);
  219. echo(s,"\n\n行為: ");
  220. if (nowCrc==srcCrc) //比較CRC,是否出錯
  221. echo(s,"接受");
  222. else
  223. echo(s,"丟棄");
  224. printf(" 前次CRC:%d",srcCrc);
  225. }
  226. fclose(fpOut);
  227. echo(s,"\n\n");
  228. return 0;
  229. }
  230. void choice()
  231. {
  232. int choice;
  233. echo(s,"1.幀封裝\n");
  234. echo(s,"2.幀解析\n");
  235. echo(s,"3.退出\n");
  236. echo(s,"\t請選擇序號:");
  237. scanf("%d",&choice);
  238. switch(choice)
  239. {
  240. case 1:
  241. encapsulation();
  242. break;
  243. case 2:
  244. unPack();
  245. break;
  246. case 3:
  247. echo(s,"歡迎使用....\n");
  248. exit(0);
  249. default:
  250. putchar('\a');
  251. echo(s,"序號在1-3,請重新選擇\n");
  252. }
  253. }
  254. int main(int argc,char **argv)
  255. {
  256. while(1)
  257. {
  258. choice();
  259. echo(s,"\n");
  260. }
  261. return 0;
  262. }

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

Copyright © Linux教程網 All Rights Reserved