C語言實現MAC幀的封裝與解封裝
阿新 • • 發佈:2019-01-04
這周做計算機網路課程設計,在幾個題目中選了個MAC幀的封裝.
首先看最後結果:
這裡有個bug,不知道為什麼幀前導碼和幀定界符前多了FFFFFF,我自己沒搞懂???
程式如下:
/* 目標: 封裝 1.將inputFile檔案中的資料封裝成MAC幀,封裝好的MAC幀寫入outputFile檔案中. 2.如果資料長度小於46位元組,則補全到46位元組 3.如果資料長度大於1500,則封裝成多個MAC幀 解封裝: 讀取outputFile中的資料,並逐個顯示幀的資訊 其實我們要求還是蠻低的,上面有好多是自己新增的 */ #include <stdio.h> #include <stdlib.h> #define MAXSIZE 1500 #define echo(format,str) printf("%"#format,str) #define inputFile "inputFile.txt" #define outputFile "outputFile.txt" void flush() { fflush(stdin); fflush(stdout); } unsigned int crc8(unsigned char *ptr,unsigned int len) /* CRC校驗,ptr是需要計算的陣列首地址,len是需要計算的長度 */ { unsigned int CRC = 0; unsigned int i; while(len--){ CRC = CRC^ *ptr++; for(i = 0; i < 8; i++){ if(CRC & 0x01){ CRC = (CRC >> 1 )^ 0x8c; } else{ CRC >>= 1; } } } return CRC; } int encapsulation() /*幀封裝函式*/ { int i,dataCrc,nu,j,lastNu,sum; FILE *fpIn,*fpOut; int src[6],des[6]; char type[2],data[MAXSIZE]; if((fpIn=fopen(inputFile,"a+"))==NULL) { echo(s,"開啟檔案失敗!"); return 1; } if((fpOut=fopen(outputFile,"wb"))==NULL) { echo(s,"寫入檔案失敗"); return 1; } fseek(fpIn,0,SEEK_END); sum=ftell(fpIn); nu=sum/1500; if((sum-nu*1500)<46) { for(i=0;i<(46-(sum-nu*1500));i++) fputc(0x0,fpIn); //如果不足,則填充 } rewind(fpIn); echo(s,"請輸源MAC:"); scanf("%x-%x-%x-%x-%x-%x",src,src+1,src+2,src+3,src+4,src+5); fflush(stdin); echo(s,"請輸入目標MAC:"); scanf("%x-%x-%x-%x-%x-%x",des,des+1,des+2,des+3,des+4,des+5); flush(); echo(s,"請輸入型別欄位:"); flush(); scanf("%2x%2x",type,type+1); for(j=0;j<nu+1;j++) { for(i=0;i<7;i++) fputc(0xaa,fpOut); //寫入幀前導碼 fputc(0xab,fpOut); //寫入幀定界符 for(i=0;i<6;i++) { fputc(des[i],fpOut); //寫入目的MAC } for(i=0;i<6;i++) { fputc(src[i],fpOut); //寫入源MAC } fputc(type[0],fpOut); //寫入型別號 fputc(type[1],fpOut); if(j!=nu) /*不是最後一個數據,則前面的資料都應該是1500*/ { fread(data,sizeof(char),1500,fpIn); fwrite(data,sizeof(char),1500,fpOut); dataCrc=crc8(data,1500); fputc(dataCrc,fpOut); } else { //最後一段資料,需要額外處理,獲取長度 lastNu=ftell(fpIn); fread(data,sizeof(char),sum-lastNu,fpIn); fwrite(data,sizeof(char),sum-lastNu,fpOut); dataCrc=crc8(data,sum-lastNu); fputc(dataCrc,fpOut); } } fclose(fpIn); fclose(fpOut); echo(s,"\n\n"); return 0; } int unPack() /*解封裝函式*/ { int i,dataStart,dataEnd,srcCrc,nowCrc,dataLength,frameNu=0,sum,j; char c,data[MAXSIZE]; FILE *fpOut; if((fpOut=fopen(outputFile,"rb"))==NULL) { echo(s,"開啟檔案失敗!"); return 1; } fseek(fpOut,0,SEEK_END); sum=ftell(fpOut); rewind(fpOut); while(1) /*此迴圈為了獲取幀的個數 主要思路:連續7個0xaa,第8個是0xab */ { if(ftell(fpOut)>=sum) { break; } for(i=0;i<7;i++) { if(ftell(fpOut)>=sum) { break; } if(fgetc(fpOut)!=0xaa) { i=-1; } } if(ftell(fpOut)>=sum) { break; } if(fgetc(fpOut)==0xab) { ++frameNu; } } rewind(fpOut); for(j=0;j<frameNu;j++) /*迴圈逐個輸出幀的資訊*/ { printf("\n\n幀序號: %d\n\n",j+1); echo(s,"幀前導碼: "); for (i=0;i<7;i++) { c=fgetc(fpOut); echo(.2X,c); } echo(s,"\n\n"); echo(s,"幀前定界符: "); { c=fgetc(fpOut); echo(.2X,c); } echo(s,"\n\n"); echo(s,"目的MAC地址: "); for (i=0;i<6;i++) { c=fgetc(fpOut); echo(.2X,c); if (i!=5) echo(s,"-"); } echo(s,"\n\n"); echo(s,"源MAC地址: "); for (i=0;i<6;i++) { c=fgetc(fpOut); echo(.2X,c); if (i!=5) echo(s,"-"); } echo(s,"\n\n"); echo(s,"型別號: "); c=fgetc(fpOut); echo(.2X,c); c=fgetc(fpOut); echo(.2X,c); if(j!=frameNu-1) //不是最後一個幀,則資料長度都是1500 { fread(data,sizeof(char),1500,fpOut); srcCrc=fgetc(fpOut); nowCrc=crc8(data,1500); } else { //最後一個幀,額外處理 dataStart=ftell(fpOut); fseek(fpOut,-1,SEEK_END); dataEnd=ftell(fpOut)-1; dataLength=dataEnd-dataStart+1; srcCrc=fgetc(fpOut); fseek(fpOut,dataStart,SEEK_SET); fread(data,sizeof(char),dataLength,fpOut); nowCrc=crc8(data,dataLength); } printf("\n\n本次CRC: %d",nowCrc); echo(s,"\n\n行為: "); if (nowCrc==srcCrc) //比較CRC,是否出錯 echo(s,"接受"); else echo(s,"丟棄"); printf(" 前次CRC:%d",srcCrc); } fclose(fpOut); echo(s,"\n\n"); return 0; } void choice() { int choice; echo(s,"1.幀封裝\n"); echo(s,"2.幀解析\n"); echo(s,"3.退出\n"); echo(s,"\t請選擇序號:"); scanf("%d",&choice); switch(choice) { case 1: encapsulation(); break; case 2: unPack(); break; case 3: echo(s,"歡迎使用....\n"); exit(0); default: putchar('\a'); echo(s,"序號在1-3,請重新選擇\n"); } } int main(int argc,char **argv) { while(1) { choice(); echo(s,"\n"); } return 0; }
總的說來,這個程式還是有很多很多需要修改的地方,健壯性很差,等有時間再好好完善一下.