




版權說明:本文檔由用戶提供并上傳,收益歸屬內容提供方,若內容存在侵權,請進行舉報或認領
文檔簡介
滁州學院課程設計匯報課程名稱:計算機網絡設計題目:滑動窗口協議仿真系別:計算機與信息工程學院專業:計算機科學與技術組別:第五組起止日期:11月24日~12月7日指導老師:趙國柱計算機與信息工程學院二○一一年制課程設計題目滑動窗口協議仿真組長趙育坤學號班級計專1班系別計算機與信息工程學院專業計算機科學與技術組員閆婷、張俠、余靜、于東鋒、張飛、趙育坤指導老師趙國柱課程設計目掌握滑動窗口協議基礎原理,并能夠用所學計算機高級語言進行編程模擬課程設計所需環境開發環境:
VC++運行環境:Windows操作系統課程設計任務要求1.程序根據滑動窗口協議實現端對端數據傳送。包含協議多種策略,如包丟失、停等應答、超時等都應有所仿真實現2.顯示數據傳送過程中各項具體數據。雙方幀個數改變,幀序號,發送和接收速度,暫停或重傳提醒等課程設計工作進度計劃序號起止日期工作內容分工情況111月24號~11月27號了解工作要求,明確分工內容,網上查閱相關資料全部組員共同參與211月28號~11月30號sender隊列模塊編寫由閆婷完成312月1號~12月4號sender主函數編寫由趙育坤、張飛完成411月28號~11月30號receiver隊列模塊編寫由張俠完成512月1號~12月4號receiver主函數編寫由余靜、于東鋒完成612月5號~12月7號最終匯總,調試由趙育坤、于東鋒完成指導老師簽字:年月日教研室審核意見:教研室主任簽字:年月日課程設計任務書一.引言二.基礎原理2.1窗口機制2.21bit滑動窗口協議2.3后退N協議2.4選擇重傳協議2.5流量控制三.需求分析3.1課程設計題目3.2開發環境3.3運行環境3.4課程設計任務及要求3.5界面要求3.6網絡接口要求四.具體設計
4.1結構體定義4.2發送方關鍵函數4.3接收方關鍵函數五.源代碼5.1發送方關鍵代碼5.2接收方關鍵代碼六.調試與操作說明致謝[參考文件]課程設計關鍵內容1.引言早期網絡通信中,通信雙方不會考慮網絡擁擠情況直接發送數據。因為大家不知道網絡擁塞情況,一起發送數據,造成中間結點阻塞掉包,誰也發不了數據。在數據傳輸過程中,我們總是期望數據傳輸愈加快部分,但假如發送方把數據發送過快,接收方就可能來不及接收,這就造成數據丟失。所以就有了滑動窗口機制來處理這些問題。早期我們使用是1bit滑動窗口協議,一次只發送一個幀,等收到ack確定才發下一個幀,這么對信道利用率太低了。所以提出了一個采取累積確定連續ARQ協議,接收方無須對收到幀逐一發送ack確定,而是收到多個幀后,對按序抵達最終一個幀發送ack確定。同1bit滑動窗口協議相比,大大降低了ack數量,并消除了延遲ack對傳輸效率影響。不過,這會產生一個新問題,假如發送方發送了5個幀,而中間第3個幀丟失了。這時接收方只能對前2個幀發出確定。發送方無法知道后面三個幀下落,只好把后面3個幀再重傳一次,這就是回退N協議。為了處理這個問題,又提出了選擇重傳協議。當接收方發覺某幀犯錯后,繼續接收后面送來正確幀,只是不交付它們,存放在自己緩沖區中,而且要求發送方重傳犯錯那一幀。一旦收到重傳來幀后,就能夠將存于緩沖區中其它幀一并按正確次序遞交給主機。2.基礎原理2.1窗口機制滑動窗口協議基礎原理就是在任意時刻,發送方都維持了一個連續許可發送幀序號,稱為發送窗口;同時,接收方也維持了一個連續許可接收幀序號,稱為接收窗口。發送窗口和接收窗口序號上下界不一定要一樣,甚至大小也能夠不一樣。不一樣滑動窗口協議窗口大小通常不一樣。發送方窗口內序號代表了那些已經被發送,不過還沒有被確定幀,或者是那些能夠被發送幀。接收方為其窗口內每一個序號保留了一個緩沖區。與每個緩沖區相關聯還有一位,用來指明該緩沖區是滿還是空。
若從滑動窗口見解來統一看待1比特滑動窗口、后退n及選擇重傳三種協議,它們差異僅在于各自窗口尺寸大小不一樣而已。1比特滑動窗口協議:發送窗口=1,接收窗口=1;后退N協議:發送窗口>1,接收窗口=1;選擇重傳協議:發送窗口>1,接收窗口>1。2.21bit滑動窗口協議當發送窗口和接收窗口大小固定為1時,滑動窗口協議退化為停等協議(stop-and-wait)。該協議要求發送方每發送一幀后就要停下來,等候接收方已正確接收確定(acknowledgement)返回后才能繼續發送下一幀。因為接收方需要判定接收到幀是新發幀還是重新發送幀,所以發送方要為每一個幀加一個序號。因為停等協議要求只有一幀完全發送成功后才能發送新幀,所以只用一比特來編號就夠了。其發送方和接收方運行步驟圖如圖所表示。2.3后退N協議因為停等協議要為每一個幀進行確定后才繼續發送下一幀,大大降低了信道利用率,所以又提出了后退n協議。后退n協議中,發送方在發完一個數據幀后,不停下來等候應答幀,而是連續發送若干個數據幀,即使在連續發送過程中收到了接收方發來應答幀,也能夠繼續發送。且發送方在每發送完一個數據幀時都要設置超時定時器。只要在所設置超時時間內仍收到確定幀,就要重發對應數據幀。如:當發送方發送了N個幀后,若發覺該N幀前一個幀在計時器超時后仍未返回其確定信息,則該幀被判為犯錯或丟失,此時發送方就不得不重新發送犯錯幀及其后N幀。從這里不難看出,后退n協議首先因連續發送數據幀而提升了效率,但其次,在重傳時又必需把原來已正確傳送過數據幀進行重傳(僅因這些數據幀之前有一個數據幀出了錯),這種做法又使傳送效率降低。由此可見,若傳輸信道傳輸質量很差所以誤碼率較大時,連續測協議不一定優于停止等候協議。此協議中發送窗口大小為k,接收窗口仍是1。2.4選擇重傳協議在后退n協議中,接收方若發覺錯誤幀就不再接收后續幀,即使是正確抵達幀,這顯然是一個浪費。另一個效率更高策略是當接收方發覺某幀犯錯后,其后繼續送來正確幀即使不能立刻遞交給接收方高層,但接收方仍可收下來,存放在一個緩沖區中,同時要求發送方重新傳送犯錯那一幀。一旦收到重新傳來幀后,就能夠原已存于緩沖區中其它幀一并按正確次序遞交高層。這種方法稱為選擇重發(SELECTICEREPEAT),其工作過程如圖所表示。顯然,選擇重發降低了浪費,但要求接收方有足夠大緩沖區空間。2.5流量控制TCP特點之一是提供體積可變滑動窗口機制,支持端到端流量控制。TCP窗口以字節為單位進行調整,以適應接收方處理能力。處理過程以下:(1)TCP連接階段,雙方協商窗口尺寸,同時接收方預留數據緩存區;(2)發送方依據協商結果,發送符合窗口尺寸數據字節流,并等候對方確定;(3)發送方依據確定信息,改變窗口尺寸,增加或者降低發送未得到確定字節流中字節數。調整過程包含:假如出現發送擁塞,發送窗口縮小為原來二分之一,同時將超時重傳時間間隔擴大一倍。(4)滑動窗口機制為端到端設備間數據傳輸提供了可靠流量控制機制。然而,它只能在源端設備和目端設備起作用,當網絡中間設備(比如路由器等)發生擁塞時,滑動窗口機制將不起作用。3.需求分析3.1課程設計題目:滑動窗口協議仿真3.2開發環境:VisualC++6.03.3運行環境:Windows操作系統3.4課程設計任務及要求:
(1)程序根據滑動窗口協議實現端對端數據傳送。包含協議多種策略,如包丟失、停等應答、超時等都應有所仿真實現。
(2)顯示數據傳送過程中各項具體數據。雙方幀個數改變,幀序號,發送和接收速度,暫?;蛑貍魈嵝训?。3.5界面要求:此次課程設計要求全部功效應可視,我們組關鍵是用VC++編寫,運行在DOS環境下,觀察發送方(sender)發送數據包到接收方(receive)時。界面應顯示出雙方幀個數改變,幀序號,發送和接收速度,暫停或重傳提醒等,界面中必需動態顯示數據幀發送和接收情況,包含在對應窗口具體顯示對應ACK和其她收發數據幀后發出消息,以表明模擬協議正確運作過程。在多種情況下,接收方和發送方窗口應實時顯示幀發送和接收情況,包含序號,時間戳,內容等。以及窗口填充和清空情況。
3.6網絡接口要求:兩臺機器或是一臺機器中兩個獨立線程模擬發送方與接收方,接收數據端口初始應為監聽狀態。發送方向接收方提議連接,成功后開始發送數據。4.概要設計4.1結構體定義以下:typedefenum{data=1,ack,nak,tout}frame_kind;//幀類型typedefstructframe_head{frame_kindkind;//幀類型unsignedintseq;//序列號unsignedintack;//確定號unsignedchardata[MAX_LENGTH];//數據}Head;typedefstructframe{frame_headhead;//幀頭unsignedintsize;//數據大小}Frame;typedefstructframenode//隊列節點類型{framehead_data;structframenode*next;}Framenode;typedefstruct{Framenode*front;//隊頭指針Framenode*rear;//隊尾指針}LinkQueue;4.2發送方關鍵函數實現:函數名:voidInitLine(LinkQueue*q); 功能:初始化隊列。函數名:voidGetFrameFromHost(LinkQueue*q);功能:從主機取數據幀,因為試驗需要,假設主機有足夠多數據幀要發送。voidDeLine(LinkQueue*q); 功能:數據幀發送完成(收到確定幀)后,刪除發送數據幀(隊頭)。函數名:intQueueEmpty(LinkQueue*q); 功能:判定隊列是否為空。函數名:frameQueueFront(LinkQueue*q); 功能:取隊頭,首幀是準備好待發送幀。函數名:intQueueLen(LinkQueue*q);功能:計算隊列長度。函數名:DWORDWINAPIReceiveFun(LPVOIDpArg);功能:發送線程調用函數,pArg參數存接收幀指針。函數名:voidmain();功能:發送方主函數,首先和接收方(本機"127.0.0.1")建立socket連接并初始化發送隊列。然后反復下面步驟:(1)從主機取數據幀;(2)發送數據幀,含超時重發(接收方未收到或未收到接收方ack)和錯誤重發(收到接收方nak);(3)設置超時計時器,這里是5秒;(4)等候確定,調用CreateThread()函數創建一個線程,超時則調用TerminateThread()函數結束線程并再次發送數據幀。收到數據幀則做后續處理;(5)收到否認幀nak則再次發送數據幀,收到確定幀ack則發送下一個數據幀;(6)假如發送測試時間達成20秒,則提醒是否繼續測試,按‘q’或‘Q’退出測試。4.3接收方關鍵函數實現:函數名:voidInitLine(LinkQueue*q);功能:初始化隊列。函數名:voidGetFrameFromHost(LinkQueue*q);功能:準備好接收幀緩沖池,首幀是待接收幀,尾幀是已經接收待提交主機幀。因為試驗需要,假設數據幀送往主機是足夠快。intDeLine(LinkQueue*q,frame*pf,unsignedintcurw)功能:將幀數據保留供提交主機,curw是打開待接收數據窗口。函數名:intQueueEmpty(LinkQueue*q);功能:判定隊列是否為空。函數名:intQueueLen(LinkQueue*q);功能:計算隊列長度。函數名:voidmain();功能:接收方主函數,首先和發送方建立socket連接并初始化初始化接收窗口。然后反復下面步驟:(1)等候,接收數據幀;(2)校驗數據幀,假定產生結果,20%概率校驗錯誤或發送方發送數據幀超時;(3)校驗錯誤時,丟棄數據幀,并發送否認幀nak;(4)假如出現接收超時(假定未收到發送方發送數據幀),則不給發送發任何回應;(5)假如校驗正確,首先判定是否是上一幀重發。是上一幀重發,則丟棄數據幀,并發送確定幀ack;是新數據幀,則保留數據幀到目前接收窗口,并發送確定幀ack。(6)送數據幀至主機。5.源代碼5.1發送方關鍵代碼:voidInitLine(LinkQueue*q){ q->front=q->rear=NULL;}intQueueEmpty(LinkQueue*q){ returnq->front==NULL&&q->rear==NULL;}frameQueueFront(LinkQueue*q){ if(QueueEmpty(q)){printf("隊列為空!\n"); Sleep(SLEEPMS);exit(0);} returnq->front->head_data;}intQueueLen(LinkQueue*q){ if(QueueEmpty(q)){ return0;} intnum=0; Framenode*p=q->front; while(p!=NULL) { num++; p=p->next; } returnnum;}voidGetFrameFromHost(LinkQueue*q){ if(QueueLen(q)>=MAXPOOL) { printf("data%d已準備好\n",q->front->head_data.head.seq); return; } Framenode*p=(Framenode*)malloc(sizeof(Framenode)); memset(p->head_data.head.data,0,MAX_LENGTH); srand((unsigned)time(NULL)); p->head_data.size=rand()%MAX_LENGTH;//幀大小生成 memset(p->head_data.head.data,'1',p->head_data.size); p->head_data.head.ack=-1; p->head_data.head.kind=data; p->head_data.head.seq=0; p->next=NULL; if(QueueEmpty(q)) q->front=q->rear=p;//首幀是待發送幀 else { p->head_data.head.seq=(q->rear->head_data.head.seq+1)%MAXPOOL; q->rear->next=p; q->rear=p; } printf("從主機得到:data%d,放入緩存\n",p->head_data.head.seq); GetFrameFromHost(q);//因為試驗需要,假設主機有足夠多數據幀要發送}voidDeLine(LinkQueue*q){ Framenode*p=NULL; if(QueueEmpty(q)) { printf("隊列為空!\n"); } else { p=q->front; q->front=p->next; if(q->rear==p)q->rear=NULL; printf("發送data%d,%d成功!從緩存中刪除\n",p->head_data.head.seq,p->head_data.size); free(p); p=NULL; }}voidmain(){printf("建立連接...\n");Begin: WORDwVersionRequested;WSADATAwsaData;//初始化socket庫 wVersionRequested=MAKEWORD(1,1);//兩個byte型合并成一個WORD型 interr=WSAStartup(wVersionRequested,&wsaData); if(err!=0){ Sleep(SLEEPMS);return;} if(LOBYTE(wsaData.wVersion)!=1||HIBYTE(wsaData.wVersion)!=1) {WSACleanup();//中止WindowsSockets服務WSAStartup()成對使用 Sleep(SLEEPMS);return;} socketClient=socket(AF_INET,SOCK_STREAM,0);//監聽套接字 SOCKADDR_INclientadd;clientadd.sin_addr.S_un.S_addr=inet_addr("127.0.0.1");clientadd.sin_family=AF_INET;clientadd.sin_port=htons(7001);//設置連接端IP、端口 if(SOCKET_ERROR==connect(socketClient,(SOCKADDR*)&clientadd,sizeof(SOCKADDR)))//連接 { WSACleanup(); Sleep(SLEEPMS); gotoBegin; } chargetData[RECEIVE_MAX_LENGTH]; memset(getData,0,RECEIVE_MAX_LENGTH);//清零 if(recv(socketClient,getData,RECEIVE_MAX_LENGTH,0)==SOCKET_ERROR)//接收{printf("接收連接提醒信息犯錯!\n");}else{printf("%s\n",getData);} charsendData[SEND_MAX_LENGTH]; memset(sendData,0,SEND_MAX_LENGTH);strcpy(sendData,"你好接收方,我是發送方!"); if(SOCKET_ERROR==send(socketClient,sendData,strlen(sendData)+1,0))//發送{printf("發送連接提醒信息犯錯!\n"); WSACleanup(); closesocket(socketClient); Sleep(SLEEPMS);return;} printf("按任意鍵繼續!\n"); while(!kbhit()){};//等候開始 Sleep(SLEEPMS); printf("1bit滑動窗口協議:發送方,發送窗口=1\n"); LinkQueueQueueQ; InitLine(&QueueQ); framepacketsend;//data framepacketreceive;//ack,nak unsignedlongtick=GetTickCount(); intret=0; HANDLEhThread; while(1) { GetFrameFromHost(&QueueQ); //從主機取數據幀 memset(&packetsend,0,sizeof(packetsend)); Sleep(SLEEPMS); printf("\n"); packetsend=QueueFront(&QueueQ);//取數據幀 ret=send(socketClient,(char*)&packetsend,sizeof(packetsend),0);//發送data if(ret==SOCKET_ERROR) { printf("發送數據犯錯!\n"); continue; }printf("發送數據幀:data%d,%d\n",packetsend.head.seq,packetsend.size); constunsignedlongtimeOut=5*1000;//設置超時計時器5秒超時 memset(&packetreceive,0,sizeof(packetreceive)); Sleep(SLEEPMS); printf("\n"); InitializeCriticalSection(&gCS);//初始化臨界區 hThread=CreateThread(NULL,0,ReceiveFun,(LPVOID)&packetreceive,0,NULL); intr=WaitForMultipleObjects(1,&hThread,TRUE,timeOut); DeleteCriticalSection(&gCS);//與InitializeCriticalSection(&gCS);成對使用 if(ret==SOCKET_ERROR||ret==SOCKET_DISCONN) { printf("接收犯錯!Pressanykeytocontinue\n"); while(!kbhit()){}; continue; }if(r==WSA_WAIT_TIMEOUT)//判定超時 { TerminateThread(hThread,0);//終止線程 printf("超時重傳:data%d,%d\n",packetsend.head.seq,packetsend.size); }elseif(packetsend.head.seq==packetreceive.head.ack) { srand((unsigned)time(NULL)); switch(rand()%5)//假定產生結果,20%概率超時 { case0: printf("接收方發送回復超時(ack丟失模擬):%d\n",packetsend.head.seq); printf("超時重傳:data%d,%d\n",packetsend.head.seq,packetsend.size); break; default: if(packetreceive.head.kind==ack) { printf("接收ack幀:ack%d\n",packetreceive.head.ack); DeLine(&QueueQ); } elseif(packetreceive.head.kind==nak) { printf("接收nak幀:nak%d\n",packetsend.head.seq); } break; } } elseprintf("幀序號犯錯:%d\n",packetreceive.head.ack); if(GetTickCount()-tick>20*TIMEOUT)//設置時間20秒 { printf("連續時間20s.按q退出,其她鍵繼續\n"); intkbc=getch(); if(kbc=='q'||kbc=='Q') break; } } printf("按任意鍵退出!\n"); while(!kbhit()){}; Sleep(SLEEPMS); printf("謝謝使用!\n"); WSACleanup(); closesocket(socketClient); Sleep(SLEEPMS);}DWORDWINAPIReceiveFun(LPVOIDpArg){ EnterCriticalSection(&gCS);//進入criticalsection frame*packetreceive=(frame*)pArg; ret=recv(socketClient,(char*)packetreceive,sizeof(*packetreceive),0); LeaveCriticalSection(&gCS); //線程用畢,離開criticalsection returnret;}5.2接收方關鍵代碼:voidInitLine(LinkQueue*q){ q->front=q->rear=NULL;}intQueueEmpty(LinkQueue*q){ returnq->front==NULL&&q->rear==NULL;}frameQueueFront(LinkQueue*q){ if(QueueEmpty(q)){printf("隊列為空!\n"); Sleep(SLEEPMS);exit(0);} returnq->front->head_data;}intQueueLen(LinkQueue*q){ if(QueueEmpty(q)){ return0;} intnum=0; Framenode*p=q->front; while(p!=NULL) { num++; p=p->next; } returnnum;}intGetFrameFromHost(LinkQueue*q){ if(QueueLen(q)>=MAXPOOL) { printf("準備接收:data%d\n",q->front->head_data.head.seq); returnq->front->head_data.head.seq; } Framenode*p=(Framenode*)malloc(sizeof(Framenode)); memset(p->head_data.head.data,0,MAX_LENGTH); p->head_data.head.ack=-1; p->head_data.head.kind=ack; p->head_data.head.seq=0; p->next=NULL; if(QueueEmpty(q))q->front=q->rear=p; else { p->head_data.head.seq=(q->rear->head_data.head.seq+1)%MAXPOOL; q->rear->next=p; q->rear=p; } returnGetFrameFromHost(q);}intDeLine(LinkQueue*q,frame*pf,unsignedintcurw)//假設數據幀送往主機是足夠快{ Framenode*p=NULL; if(curw==q->front->head_data.head.seq) p=q->front; else p=q->rear; if(p->head_data.head.ack!=-1)//假定數據已經提交主機 { printf("向主機交付data%d,%d成功!\n",p->head_data.head.ack,p->head_data.size); } memset(p->head_data.head.data,0,MAX_LENGTH); memcpy(p->head_data.head.data,pf->head.data,pf->size); p->head_data.size=pf->size; p->head_data.head.ack=pf->head.seq;//保留發送幀序號 returnp->head_data.head.seq;}frameQueueAnswer(LinkQueue*q,unsignedintcurw){ if(curw==q->front->head_data.head.seq) { returnq->front->head_data; } else { returnq->rear->head_data; }}voidmain(){Begin:WORDwVersionRequested;WSADATAwsaData;//初始化socket庫wVersionRequested=MAKEWORD(1,1);//兩個byte型合并成一個WORD型interr=WSAStartup(wVersionRequested,&wsaData);//使用sockets之前要調用一次 if(err!=0){ Sleep(SLEEPMS);return;} if(LOBYTE(wsaData.wVersion)!=1||HIBYTE(wsaData.wVersion)!=1){WSACleanup();//中止WindowsSockets服務WSAStartup()成對使用 Sleep(SLEEPMS);return;} SOCKETsocksrv=socket(AF_INET,SOCK_STREAM,0);//監聽套接字SOCKADDR_INsocketadd;socketadd.sin_addr.S_un.S_addr=htonl(INADDR_ANY);//監聽連接socketadd.sin_family=AF_INET;socketadd.sin_port=htons(7001);//設置端口 if(SOCKET_ERROR==bind(socksrv,(SOCKADDR*)&socketadd,sizeof(SOCKADDR))){printf("綁定犯錯!\n"); WSACleanup(); Sleep(SLEEPMS);return;}if(SOCKET_ERROR==listen(socksrv,5)){printf("監聽犯錯!"); WSACleanup(); Sleep(SLEEPMS);return;} SOCKADDR_INsockclient;intlen=sizeof(SOCKADDR);SOCKETsockconn=accept(socksrv,(SOCKADDR*)&sockclient,&len);//建立連接套節字if(INVALID_SOCKET==sockconn){printf("建立連接犯錯!\n"); WSACleanup(); Sleep(SLEEPMS);return;} charsendData[SEND_MAX_LENGTH]; memset(sendData,0,SEND_MAX_LENGTH);sprintf(sendData,"%s","你好發送方,我是接收方!");if(SOCKET_ERROR==send(sockconn,sendData,strlen(sendData)+1,0)){printf("發送連接提醒信息犯錯!\n"); WSACleanup(); closesocket(sockconn); Sleep(SLEEPMS);return;} chargetData[RECEIVE_MAX_LENGTH]; memset(getData,0,RECEIVE_MAX_LENGTH);recv(sockconn,getData,RECEIVE_MAX_LENGTH,0);printf("%s\n",getData); printf("1bit滑動窗口協議:接收方,接收窗口=1\n"); LinkQueueQueueQ; InitLine(&QueueQ); framepacketreceive;//data framepacketsend;//ack,nak intcurw=GetFrameFromHost(&QueueQ);//初始化接收窗口 intret=0; while(1) { memset(&packetreceive,0,sizeof(packetreceive)); Sleep(SLEEPMS); printf("\n"); ret=recv(sockconn,(char*)&packetreceive,sizeof(packetreceive),0); if(ret==SOCKET_ERROR||ret==SOCKET_DISCONN) { if(ret==SOCKET_ERROR) { printf("連接犯錯!自動連接!\n"); continue; } else { printf("連接已斷開,按q退出,其她鍵等候新連接\n"); intkbc=getch(); if(kbc=='q'||kbc=='Q') break; else { WSACleanup(); closesocket(sockconn); Sleep(SLEEPMS); gotoBegin; } } } srand((unsigned)time(NULL)); switch(rand()%5)//假定產生結果,20%概率校驗錯誤或接收發送方超時 { case0: printf("接收數據幀:data%d,%d,校驗錯誤,丟棄(數據幀犯錯模擬)\n",packetreceive.head.seq,packetreceive.size); memset(&packetsend,0,sizeof(packetsend)); memcpy(&packetsend,&packetreceive,sizeof(packetreceive)); packetsend.head.ack=packetreceive.head.seq; packetsend.head.seq=curw; packetsend.head.kind=nak; printf("發送否認幀:nak%d\n",packetreceive.head.seq); break; case1: packetsend.head.kind=tout; printf("發送方發送數據超時(數據幀丟失模擬):%d\n",packetreceive.head.seq); break; default: printf("接收數據幀:data%d,%d,校驗正確
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯系上傳者。文件的所有權益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網頁內容里面會有圖紙預覽,若沒有圖紙預覽就沒有圖紙。
- 4. 未經權益所有人同意不得將文件中的內容挪作商業或盈利用途。
- 5. 人人文庫網僅提供信息存儲空間,僅對用戶上傳內容的表現方式做保護處理,對用戶上傳分享的文檔內容本身不做任何修改或編輯,并不能對任何下載內容負責。
- 6. 下載文件中如有侵權或不適當內容,請與我們聯系,我們立即糾正。
- 7. 本站不保證下載資源的準確性、安全性和完整性, 同時也不承擔用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
評論
0/150
提交評論