




下載本文檔
版權(quán)說明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請進行舉報或認(rèn)領(lǐng)
文檔簡介
1、.滁州學(xué)院課程設(shè)計報告課程名稱:計算機網(wǎng)絡(luò)設(shè)計題目 :滑動窗口協(xié)議仿真系別:計算機與信息工程學(xué)院專業(yè):計算機科學(xué)與技術(shù)組別:第五組起止日期 : 2011 年 11 月 24 日2011 年 12 月 7 日指導(dǎo)教師 :趙國柱計算機與信息工程學(xué)院二一一年制;.課程設(shè)計題目滑動窗口協(xié)議仿真組長趙育坤學(xué)號2011220135班級計專 1班系別計算機與信息專業(yè)計算機科學(xué)與技術(shù)工程學(xué)院組員閆婷、張俠、余靜、于東鋒、張飛、趙育坤指導(dǎo)教師趙國柱課程設(shè)計目的掌握滑動窗口協(xié)議的基本原理,并能夠用所學(xué)計算機高級語言進行編程模擬課程設(shè)計所需環(huán)境開發(fā)環(huán)境 :VC+運行環(huán)境 : Windows操作系統(tǒng)1程序按照滑動窗口
2、協(xié)議實現(xiàn)端對端的數(shù)據(jù)傳送。包括協(xié)議的各課程設(shè)計任務(wù)要求種策略,如包丟失、停等應(yīng)答、超時等都應(yīng)有所仿真實現(xiàn)2顯示數(shù)據(jù)傳送過程中的各項具體數(shù)據(jù)。雙方幀的個數(shù)變化,幀序號,發(fā)送和接受速度,暫停或重傳提示等課程設(shè)計工作進度計劃序號起止日期工 作內(nèi) 容分工情況111月24號了解工作要求, 明確分工內(nèi)所有組員共同參與11月 27號容,網(wǎng)上查閱相關(guān)資料211月28號sender隊列模塊的編寫由閆婷完成11月 30號312月1號sender 主函數(shù)的編寫由趙育坤、張飛完成12月4號411月28號receiver隊列模塊的編寫由張俠完成11月 30號512月1號receiver主函數(shù)的編寫由余靜、于東鋒完成12
3、月4號612月5號最后匯總,調(diào)試由趙育坤、于東鋒完成12月7號指導(dǎo)教師簽字:年月日教研室審核意見:教研室主任簽字:年月日;.課程設(shè)計任務(wù)書一 . 引言二. 基本原理2.1 窗口機制2.2 1bit 滑動窗口協(xié)議2.3 后退 N 協(xié)議2.4 選擇重傳協(xié)議2.5 流量控制三. 需求分析3.1 課程設(shè)計題目3.2 開發(fā)環(huán)境3.3 運行環(huán)境3.4 課程設(shè)計任務(wù)及要求3.5 界面要求3.6網(wǎng)絡(luò)接口要求四.詳細設(shè)計4.1結(jié)構(gòu)體的定義4.2發(fā)送方的主要函數(shù)4.3接受方的主要函數(shù)五 . 源代碼5.1發(fā)送方的主要代碼5.2 接收方的主要代碼六 . 調(diào)試與操作說明致謝 參考文獻 ;.課程設(shè)計的主要內(nèi)容1. 引言早
4、期的網(wǎng)絡(luò)通信中,通信雙方不會考慮網(wǎng)絡(luò)的擁擠情況直接發(fā)送數(shù)據(jù)。由于大家不知道網(wǎng)絡(luò)擁塞狀況,一起發(fā)送數(shù)據(jù),導(dǎo)致中間結(jié)點阻塞掉包,誰也發(fā)不了數(shù)據(jù)。在數(shù)據(jù)傳輸過程中,我們總是希望數(shù)據(jù)傳輸?shù)母煲恍?,但如果發(fā)送方把數(shù)據(jù)發(fā)送的過快,接收方就可能來不及接收,這就造成數(shù)據(jù)的丟失。因此就有了滑動窗口機制來解決這些問題。早期我們使用的是1bit滑動窗口協(xié)議,一次只發(fā)送一個幀,等收到ack 確認(rèn)才發(fā)下一個幀,這樣對信道的利用率太低了。因此提出了一種采用累積確認(rèn)的連續(xù)ARQ協(xié)議, 接收方不必對收到的幀逐個發(fā)送ack 確認(rèn),而是收到幾個幀后,對按序到達的最后一個幀發(fā)送ack 確認(rèn)。同1bit滑動窗口協(xié)議相比,大大減少了
5、ack 數(shù)量,并消除了延遲ack對傳輸效率的影響。但是,這會產(chǎn)生一個新的問題,如果發(fā)送方發(fā)送了5 個幀,而中間的第3 個幀丟失了。這時接收方只能對前2 個幀發(fā)出確認(rèn)。發(fā)送方無法知道后面三個幀的下落,只好把后面的 3 個幀再重傳一次, 這就是回退 N 協(xié)議。為了解決這個問題, 又提出了選擇重傳協(xié)議。 當(dāng)接收方發(fā)現(xiàn)某幀出錯后,繼續(xù)接受后面送來的正確的幀,只是不交付它們,存放在自己的緩沖區(qū)中,并且要求發(fā)送方重傳出錯的那一幀。一旦收到重傳來的幀后,就可以將存于緩沖區(qū)中的其余幀一并按正確的順序遞交給主機。2. 基本原理2.1窗口機制滑動窗口協(xié)議的基本原理就是在任意時刻,發(fā)送方都維持了一個連續(xù)的允許發(fā)送的
6、幀的序號,稱為發(fā)送窗口;同時,接收方也維持了一個連續(xù)的允許接收的幀的序號,稱為接收窗口。發(fā)送窗口和接收窗口的序號的上下界不一定要一樣,甚至大小也可以不同。不同的滑動窗口協(xié)議窗口大小一般不同。發(fā)送方窗口內(nèi)的序號代表了那些已經(jīng)被發(fā)送,但是還沒有被確認(rèn)的幀,或者是那些可以被發(fā)送的幀。接受方為其窗口內(nèi)的每一個序號保留了一個緩沖區(qū)。與每個緩沖區(qū)相關(guān)聯(lián)的還有一位,用來指明該緩沖區(qū)是滿的還是空的。若從滑動窗口的觀點來統(tǒng)一看待1 比特滑動窗口、后退n 及選擇重傳三種協(xié)議,它們的差別僅在于各自窗口尺寸的大小不同而已。1 比特滑動窗口協(xié)議:發(fā)送窗口=1 ,接收窗口 =1;后退N 協(xié)議:發(fā)送窗口>1,接收窗口
7、=1;選擇重傳協(xié)議:發(fā)送窗口>1, 接收窗口 >1。2.2 1bit滑動窗口協(xié)議當(dāng)發(fā)送窗口和接收窗口的大小固定為1 時,滑動窗口協(xié)議退化為停等協(xié)議(stop and wait )。該協(xié)議規(guī)定發(fā)送方每發(fā)送一幀后就要停下來,等待接收方已正確接收的確認(rèn)( acknowledgement)返回后才能繼續(xù)發(fā)送下一幀。由于接收方需要判斷接收到的幀是新發(fā)的幀還是重新發(fā)送的幀,因此發(fā)送方要為每一個幀加一個序號。由于停等協(xié)議規(guī)定只有一幀完全發(fā)送成功后才能發(fā)送新的幀,因而只用一比特來編號就夠了。其發(fā)送方和接收方運行的流程圖如圖所示。;.發(fā)送方接收方0-> 發(fā)送幀號0-> 期待幀號從主機取報
8、文等待裝配幀seq=發(fā)送幀號檢驗和檢查發(fā)送并設(shè)置計時器收到幀序號計時器超時=期待序號等待Ack 到達恢復(fù)報文交付主機Ack發(fā)送不對1-> 期待幀號序號對確認(rèn)幀號1-> 發(fā)送幀號Ack=seq2.3 后退 N協(xié)議由于停等協(xié)議要為每一個幀進行確認(rèn)后才繼續(xù)發(fā)送下一幀,大大降低了信道利用率,因此又提出了后退n 協(xié)議。后退 n 協(xié)議中,發(fā)送方在發(fā)完一個數(shù)據(jù)幀后,不停下來等待應(yīng)答幀,而是連續(xù)發(fā)送若干個數(shù)據(jù)幀,即使在連續(xù)發(fā)送過程中收到了接收方發(fā)來的應(yīng)答幀,也可以繼續(xù)發(fā)送。且發(fā)送方在每發(fā)送完一個數(shù)據(jù)幀時都要設(shè)置超時定時器。只要在所設(shè)置的超時時間內(nèi)仍收到確認(rèn)幀,就要重發(fā)相應(yīng)的數(shù)據(jù)幀。如:當(dāng)發(fā)送方發(fā)送
9、了N個幀后,若發(fā)現(xiàn)該N 幀的前一個幀在計時器超時后仍未返回其確認(rèn)信息,則該幀被判為出錯或丟失,此時發(fā)送方就不得不重新發(fā)送出錯幀及其后的N 幀。從這里不難看出,后退n 協(xié)議一方面因連續(xù)發(fā)送數(shù)據(jù)幀而提高了效率,但另一方面,在重傳時又必須把原來已正確傳送過的數(shù)據(jù)幀進行重傳(僅因這些數(shù)據(jù)幀之前有一個數(shù)據(jù)幀出了錯),這種做法又使傳送效率降低。由此可見,若傳輸信道的傳輸質(zhì)量很差因而誤碼率較大時,連續(xù)測協(xié)議不一定優(yōu)于停止等待協(xié)議。此協(xié)議中的發(fā)送窗口的大小為 k,接收窗口仍是 1。2.4選擇重傳協(xié)議在后退n 協(xié)議中, 接收方若發(fā)現(xiàn)錯誤幀就不再接收后續(xù)的幀,即使是正確到達的幀,這顯然是一種浪費。另一種效率更高的
10、策略是當(dāng)接收方發(fā)現(xiàn)某幀出錯后,其后繼續(xù)送來;.的正確的幀雖然不能立即遞交給接收方的高層,但接收方仍可收下來,存放在一個緩沖區(qū)中,同時要求發(fā)送方重新傳送出錯的那一幀。一旦收到重新傳來的幀后,就可以原已存于緩沖區(qū)中的其余幀一并按正確的順序遞交高層。這種方法稱為選擇重發(fā)(SELECTICEREPEAT),其工作過程如圖所示。顯然,選擇重發(fā)減少了浪費,但要求接收方有足夠大的緩沖區(qū)空間。2.5流量控制TCP 的特點之一是提供體積可變的滑動窗口機制,支持端到端的流量控制。TCP的窗口以字節(jié)為單位進行調(diào)整,以適應(yīng)接收方的處理能力。處理過程如下:( 1 ) TCP 連接階段,雙方協(xié)商窗口尺寸,同時接收方預(yù)留數(shù)
11、據(jù)緩存區(qū);( 2 )發(fā)送方根據(jù)協(xié)商的結(jié)果,發(fā)送符合窗口尺寸的數(shù)據(jù)字節(jié)流,并等待對方的確認(rèn);( 3)發(fā)送方根據(jù)確認(rèn)信息,改變窗口的尺寸,增加或者減少發(fā)送未得到確認(rèn)的字節(jié)流中的字節(jié)數(shù)。調(diào)整過程包括:如果出現(xiàn)發(fā)送擁塞,發(fā)送窗口縮小為原來的一半,同時將超時重傳的時間間隔擴大一倍。( 4)滑動窗口機制為端到端設(shè)備間的數(shù)據(jù)傳輸提供了可靠的流量控制機制。然而,它只能在源端設(shè)備和目的端設(shè)備起作用,當(dāng)網(wǎng)絡(luò)中間設(shè)備(例如路由器等)發(fā)生擁塞時,滑動窗口機制將不起作用。3. 需求分析3.1課程設(shè)計題目:滑動窗口協(xié)議仿真3.2開發(fā)環(huán)境: Visual C+6.03.3運行環(huán)境: Windows操作系統(tǒng)3.4課程設(shè)計任務(wù)
12、及要求:( 1)程序按照滑動窗口協(xié)議實現(xiàn)端對端的數(shù)據(jù)傳送。包括協(xié)議的各種策略,如包丟失、停等應(yīng)答、超時等都應(yīng)有所仿真實現(xiàn)。( 2)顯示數(shù)據(jù)傳送過程中的各項具體數(shù)據(jù)。雙方幀的個數(shù)變化,幀序號, 發(fā)送和接受速度,暫?;蛑貍魈崾镜取?.5界面要求:此次課程設(shè)計要求的所有功能應(yīng)可視,我們組主要是用VC+編寫的,運行在DOS環(huán)境下,觀察發(fā)送方(sender )發(fā)送數(shù)據(jù)包到接收方(receive )時。界面應(yīng)顯示出雙方幀個數(shù)的變化,幀序號,發(fā)送和接受速度,暫?;蛑貍魈崾镜?,界面中必須動態(tài)顯示數(shù)據(jù)幀的發(fā)送和接受情況, 包括在相應(yīng)的窗口詳細顯示相應(yīng)的ACK和其他收發(fā)數(shù)據(jù)幀后發(fā)出的消息,以表明模擬協(xié)議的正確運作
13、過程。 在各種情況下, 接受方和發(fā)送方窗口應(yīng)實時顯示幀的發(fā)送和接受情況,包括序號,時間戳,內(nèi)容等。以及窗口的填充和清空情況。3.6網(wǎng)絡(luò)接口要求:兩臺機器或是一臺機器中兩個獨立的線程模擬發(fā)送方與接受方,接收數(shù)據(jù)的端口初始應(yīng)為監(jiān)聽狀態(tài)。發(fā)送方向接受方發(fā)起連接,成功后開始發(fā)送數(shù)據(jù)。;.4. 概要設(shè)計4.1結(jié)構(gòu)體定義如下:typedef enum data = 1,ack,nak,tout frame_kind;/幀類型typedef struct frame_headframe_kind kind; / 幀類型unsigned int seq; / 序列號unsigned int ack; / 確認(rèn)
14、號unsigned char dataMAX_LENGTH; /數(shù)據(jù)Head;typedef struct frameframe_head head; /幀頭unsigned int size; / 數(shù)據(jù)的大小 Frame;typedef struct framenode/ 隊列節(jié)點類型frame head_data;struct framenode *next; Framenode;typedef structFramenode *front;/ 隊頭指針Framenode *rear;/ 隊尾指針 LinkQueue;4.2 發(fā)送方的主要函數(shù)實現(xiàn):函數(shù)名: void InitLine(Li
15、nkQueue *q);.功能:初始化隊列。函數(shù)名: void GetFrameFromHost(LinkQueue *q);功能:從主機取數(shù)據(jù)幀,由于實驗需要,假設(shè)主機有足夠多的數(shù)據(jù)幀要發(fā)送。void DeLine(LinkQueue *q);功能:數(shù)據(jù)幀發(fā)送完畢(收到確認(rèn)幀)后,刪除發(fā)送的數(shù)據(jù)幀(隊頭)。函數(shù)名: int QueueEmpty(LinkQueue *q);功能:判斷隊列是否為空。函數(shù)名: frame QueueFront(LinkQueue *q);功能:取隊頭,首幀是準(zhǔn)備好待發(fā)送的幀。函數(shù)名: int QueueLen(LinkQueue *q);功能:計算隊列長度。函數(shù)
16、名: DWORD WINAPI ReceiveFun(LPVOID pArg);功能:發(fā)送線程調(diào)用的函數(shù),pArg 參數(shù)存接收幀指針。函數(shù)名: void main();功能:發(fā)送方主函數(shù),首先和接收方(本機"" )建立 socket 連接并初始化發(fā)送隊列。然后重復(fù)下面的步驟:(1)從主機取數(shù)據(jù)幀;(2)發(fā)送數(shù)據(jù)幀,含超時重發(fā)(接收方未收到或未收到接收方ack)和錯誤重發(fā)(收到接收方 nak);(3)設(shè)置超時計時器,這里是5 秒;(4)等待確認(rèn),調(diào)用 CreateThread()函數(shù)創(chuàng)建一個線程,超時則調(diào)用TerminateThread() 函數(shù)結(jié)束線程并再
17、次發(fā)送數(shù)據(jù)幀。收到數(shù)據(jù)幀則做后續(xù)處理;(5)收到否認(rèn)幀 nak 則再次發(fā)送數(shù)據(jù)幀,收到確認(rèn)幀ack 則發(fā)送下一個數(shù)據(jù)幀;(6)如果發(fā)送的測試時間達到20 秒,則提示是否繼續(xù)測試,按q或 Q退出測試。4.3 接收方的主要函數(shù)實現(xiàn):函數(shù)名: void InitLine(LinkQueue *q);功能:初始化隊列。函數(shù)名: void GetFrameFromHost(LinkQueue *q);功能:準(zhǔn)備好接收幀的緩沖池,首幀是待接收的幀,尾幀是已經(jīng)接收的待提交主機的幀。由于實驗需要,假設(shè)數(shù)據(jù)幀送往主機是足夠快的。int DeLine(LinkQueue *q, frame *pf, unsign
18、ed int curw)功能:將幀數(shù)據(jù)保存供提交主機,curw 是打開的待接收數(shù)據(jù)的窗口。函數(shù)名: int QueueEmpty(LinkQueue *q);功能:判斷隊列是否為空。函數(shù)名: int QueueLen(LinkQueue *q);功能:計算隊列長度。函數(shù)名: void main();功能:接收方主函數(shù),首先和發(fā)送方建立socket 連接并初始化初始化接收窗口。然后重復(fù)下面的步驟:( 1)等待,接收數(shù)據(jù)幀;( 2)校驗數(shù)據(jù)幀,假定產(chǎn)生隨機結(jié)果,20%的概率校驗錯誤或發(fā)送方發(fā)送數(shù)據(jù)幀超時;( 3)校驗錯誤時,丟棄數(shù)據(jù)幀,并發(fā)送否認(rèn)幀nak;( 4)如果出現(xiàn)接收超時(假定未收到發(fā)送方
19、發(fā)送的數(shù)據(jù)幀),則不給發(fā)送發(fā)任何回應(yīng);;.(5)如果校驗正確,首先判斷是否是上一幀的重發(fā)。是上一幀的重發(fā),則丟棄數(shù)據(jù)幀,并發(fā)送確認(rèn)幀ack;是新的數(shù)據(jù)幀,則保存數(shù)據(jù)幀到當(dāng)前接收窗口,并發(fā)送確認(rèn)幀ack。(6)送數(shù)據(jù)幀至主機。5. 源代碼5.1發(fā)送方的主要代碼:void InitLine(LinkQueue *q)q->front = q->rear = NULL;int QueueEmpty(LinkQueue *q)return q->front = NULL && q->rear = NULL;frame QueueFront(LinkQueue *
20、q)if (QueueEmpty(q)printf(" 隊列為空! n");Sleep(SLEEPMS);exit(0);return q->front->head_data;int QueueLen(LinkQueue *q)if (QueueEmpty(q)return 0;.int num = 0;Framenode *p = q->front;while(p != NULL)num+;p = p->next;return num;void GetFrameFromHost(LinkQueue *q)if(QueueLen(q) >= M
21、AXPOOL)printf("data %d已準(zhǔn)備好 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, '
22、;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; /首幀是待發(fā)送的幀elsep->head_data.head.seq = (q->rear->head_data.head.seq + 1)%MAXPOOL;q->rear->next =p;q-&g
23、t;rear =p;printf(" 從主機得到:data %d,放入緩存 n", p->head_data.head.seq);GetFrameFromHost(q); /由于實驗需要,假設(shè)主機有足夠多的數(shù)據(jù)幀要發(fā)送void DeLine(LinkQueue *q)Framenode *p = NULL;if(QueueEmpty(q)printf(" 隊列為空! n");elsep = q->front;q->front = p->next;if (q->rear = p)q->rear = NULL;printf
24、(" 發(fā) 送 data %d, %d 成 功 ! 從 緩 存 中 刪 除 n", p->head_data.head.seq, p->head_data.size);free(p);p = NULL;.void main()printf(" 建立連接. n");Begin:WORD wVersionRequested;WSADATA wsaData; / 初始化 socket 庫wVersionRequested=MAKEWORD(1,1); /兩個 byte 型合并成一個WORD 型int err=WSAStartup(wVersionRe
25、quested,&wsaData);if(err!=0)Sleep(SLEEPMS);return;if ( LOBYTE( wsaData.wVersion ) != 1 | HIBYTE( wsaData.wVersion ) != 1 )WSACleanup();/中止 Windows Sockets 服務(wù)WSAStartup() 成對使用Sleep(SLEEPMS);return;socketClient = socket(AF_INET,SOCK_STREAM,0);/監(jiān)聽的套接字SOCKADDR_IN clientadd;clientadd.sin_addr.S_un.S_
26、addr = inet_addr("");clientadd.sin_family = AF_INET;clientadd.sin_port = htons(7001);/ 設(shè)置連接端的IP、端口if(SOCKET_ERROR=connect(socketClient,(SOCKADDR*)&clientadd,sizeof(SOCKADDR) ) /連接;.WSACleanup();Sleep(SLEEPMS);goto Begin;char getDataRECEIVE_MAX_LENGTH;memset(getData, 0, RECEIVE
27、_MAX_LENGTH); /清零if(recv(socketClient,getData,RECEIVE_MAX_LENGTH,0) = SOCKET_ERROR) /接受printf(" 接受連接提示信息出錯!n");elseprintf("%sn",getData);char sendDataSEND_MAX_LENGTH;memset(sendData, 0, SEND_MAX_LENGTH);strcpy(sendData, " 你好接收方,我是發(fā)送方!");if( SOCKET_ERROR = send(socketCli
28、ent,sendData,strlen(sendData)+1,0) ) /發(fā)送printf(" 發(fā)送連接提示信息出錯!n");WSACleanup();closesocket(socketClient);Sleep(SLEEPMS);return;printf(" 按任意鍵繼續(xù)!n");.while (!kbhit() ; /等待開始Sleep(SLEEPMS);printf("1bit滑動窗口協(xié)議:發(fā)送方,發(fā)送窗口=1n");LinkQueue QueueQ;InitLine(&QueueQ);frame packetse
29、nd; /dataframe packetreceive; / ack,nakunsigned long tick = GetTickCount();int ret = 0;HANDLE hThread;while(1)GetFrameFromHost(&QueueQ);/ 從主機取數(shù)據(jù)幀memset(&packetsend, 0, sizeof(packetsend);Sleep(SLEEPMS);printf("n");packetsend = QueueFront(&QueueQ); / 取數(shù)據(jù)幀ret = send(socketClient,
30、 (char *)&packetsend, sizeof(packetsend), 0);/ 發(fā)送 dataif(ret = SOCKET_ERROR)printf(" 發(fā)送數(shù)據(jù)出錯!n");continue;printf(" 發(fā)送數(shù)據(jù)幀:data %d, %dn", packetsend.head.seq, packetsend.size);const unsigned long timeOut = 5 * 1000; / 設(shè)置超時計時器5 秒超時memset(&packetreceive, 0, sizeof(packetreceiv
31、e);Sleep(SLEEPMS);.printf("n");InitializeCriticalSection(&gCS);/ 初始化臨界區(qū)hThread=CreateThread(NULL, 0, ReceiveFun, (LPVOID)&packetreceive, 0, NULL);int r = WaitForMultipleObjects(1, &hThread, TRUE, timeOut);DeleteCriticalSection(&gCS); /與 InitializeCriticalSection(&gCS);成
32、對使用if(ret = SOCKET_ERROR | ret = SOCKET_DISCONN)printf(" 接受出錯! Press any key to continuen");while (!kbhit() ;continue;if(r = WSA_W AIT_TIMEOUT) /判斷超時TerminateThread(hThread, 0); / 終止線程printf(" 超時重傳: data %d, %dn", packetsend.head.seq,packetsend.size);else if(packetsend.head.seq =
33、 packetreceive.head.ack)srand(unsigned)time(NULL);switch(rand() % 5) / 假定產(chǎn)生隨機結(jié)果,20%的概率超時case 0:printf(" 接收方發(fā)送回復(fù)超時(ack 丟失模擬 ):%dn", packetsend.head.seq);printf(" 超時重傳: data %d, %dn", packetsend.head.seq,packetsend.size);break;default:if(packetreceive.head.kind = ack);.printf("
34、; 接受 ack 幀: ack %dn", packetreceive.head.ack);DeLine(&QueueQ);else if(packetreceive.head.kind =nak)printf(" 接受 nak 幀: nak %dn", packetsend.head.seq);break;else printf(" 幀序號出錯:%dn", packetreceive.head.ack);if(GetTickCount() - tick > 20 * TIMEOUT) / 設(shè)置時間20 秒printf("
35、; 持續(xù)時間20s. 按 q 退出,其他鍵繼續(xù)n");int kbc = getch();if(kbc = 'q' | kbc = 'Q')break;printf(" 按任意鍵退出!n");while (!kbhit() ;Sleep(SLEEPMS);printf(" 謝謝使用! n");WSACleanup();closesocket(socketClient);Sleep(SLEEPMS);.DWORD WINAPI ReceiveFun(LPVOID pArg)EnterCriticalSection(
36、&gCS);/進入 critical sectionframe *packetreceive = (frame *)pArg;ret = recv(socketClient, (char *)packetreceive, sizeof(*packetreceive), 0);LeaveCriticalSection(&gCS);/ 線程用畢,離開critical sectionreturn ret;5.2接收方的主要代碼:void InitLine(LinkQueue *q)q->front = q->rear = NULL;int QueueEmpty(LinkQ
37、ueue *q)return q->front = NULL && q->rear = NULL;frame QueueFront(LinkQueue *q)if (QueueEmpty(q)printf(" 隊列為空! n");Sleep(SLEEPMS);exit(0);return q->front->head_data;.int QueueLen(LinkQueue *q)if (QueueEmpty(q)return 0;int num = 0;Framenode *p = q->front;while(p != NU
38、LL)num+;p = p->next;return num;int GetFrameFromHost(LinkQueue *q)if(QueueLen(q) >= MAXPOOL)printf(" 準(zhǔn)備接受: data %d n", q->front->head_data.head.seq);return q->front->head_data.head.seq;Framenode *p=(Framenode *)malloc(sizeof(Framenode);memset(p->head_data.head.data, 0,
39、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;elsep->head_data.head.seq = (q->rear->head_data.head.seq + 1)%MAXPOOL;q->rear->next =p;q->rear = p;return GetFrameFromH
40、ost(q);int DeLine(LinkQueue *q, frame *pf, unsigned int curw) /假設(shè)數(shù)據(jù)幀送往主機是足夠快的Framenode *p = NULL;if(curw = q->front->head_data.head.seq)p = q->front;elsep = q->rear;if(p->head_data.head.ack != -1) / 假定數(shù)據(jù)已經(jīng)提交主機printf(" 向主機交付data %d, %d 成功! n", p->head_data.head.ack, p->
41、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; /保存發(fā)送幀序號;.return p->head_data.head.seq;frame QueueAnswer(LinkQueue *q, unsigned int curw
42、)if(curw = q->front->head_data.head.seq)return q->front->head_data;elsereturn q->rear->head_data;void main()Begin:WORD wVersionRequested;WSADATA wsaData; / 初始化 socket 庫wVersionRequested = MAKEWORD( 1, 1 );/兩個 byte 型合并成一個WORD 型int err = WSAStartup(wVersionRequested, &wsaData );/
43、使用 sockets 之前要調(diào)用一次if ( err != 0 )Sleep(SLEEPMS);return;if ( LOBYTE( wsaData.wVersion ) != 1 | HIBYTE( wsaData.wVersion ) != 1 );.WSACleanup();/ 中止 Windows Sockets 服務(wù)WSAStartup() 成對使用Sleep(SLEEPMS);return;SOCKETsocksrv = socket(AF_INET,SOCK_STREAM,0);/監(jiān)聽的套接字SOCKADDR_IN socketadd;socketadd.sin_addr.S_
44、un.S_addr = htonl(INADDR_ANY); /監(jiān)聽連接socketadd.sin_family = AF_INET;socketadd.sin_port = htons(7001);/ 設(shè)置端口if( SOCKET_ERROR = bind(socksrv,(SOCKADDR*)&socketadd,sizeof(SOCKADDR) )printf(" 綁定出錯! n");WSACleanup();Sleep(SLEEPMS);return;if( SOCKET_ERROR = listen(socksrv,5) )printf(" 監(jiān)聽
45、出錯! ");WSACleanup();Sleep(SLEEPMS);return;SOCKADDR_IN sockclient;int len = sizeof(SOCKADDR);SOCKET sockconn = accept(socksrv,(SOCKADDR*)&sockclient,&len);/建立連接的套節(jié)字if(INV ALID_SOCKET = sockconn );.printf(" 建立連接出錯!n");WSACleanup( );Sleep(SLEEPMS);return;char sendDataSEND_MAX_LEN
46、GTH;memset(sendData, 0, SEND_MAX_LENGTH);sprintf(sendData,"%s"," 你好發(fā)送方,我是接受方!");if( SOCKET_ERROR = send(sockconn,sendData,strlen(sendData)+1,0) )printf(" 發(fā)送連接提示信息出錯!n");WSACleanup( );closesocket(sockconn);Sleep(SLEEPMS);return;char getDataRECEIVE_MAX_LENGTH;memset(getData, 0, RECEIVE_MAX_LENGTH);recv(sockconn,getData,RECEIVE_MAX_LENGTH,0);printf("%sn",getData);printf("1bit滑動窗口協(xié)議:接收方,接收窗口=1n");
溫馨提示
- 1. 本站所有資源如無特殊說明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請下載最新的WinRAR軟件解壓。
- 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
- 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁內(nèi)容里面會有圖紙預(yù)覽,若沒有圖紙預(yù)覽就沒有圖紙。
- 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
- 5. 人人文庫網(wǎng)僅提供信息存儲空間,僅對用戶上傳內(nèi)容的表現(xiàn)方式做保護處理,對用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對任何下載內(nèi)容負(fù)責(zé)。
- 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請與我們聯(lián)系,我們立即糾正。
- 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時也不承擔(dān)用戶因使用這些下載資源對自己和他人造成任何形式的傷害或損失。
最新文檔
- 賣買游戲合同范例
- 個人轉(zhuǎn)讓閑置住宅合同范本
- 2025陜西省建筑安全員-A證考試題庫附答案
- 二年級口算題目全集100道
- 2025年江西省安全員A證考試題庫附答案
- 二年級口算題目大全100道
- 二年級口算題庫匯編100道
- 二年級口算題目大全100道
- 個人沙金開采合同范本
- 人工挖孔樁合同范本
- 第四單元平行與相交(單元測試)-2024-2025學(xué)年四年級上冊數(shù)學(xué)青島版
- 2024年密碼行業(yè)職業(yè)技能競賽參考試題庫500題(含答案)
- 2024中智集團招聘重要崗位高頻難、易錯點500題模擬試題附帶答案詳解
- 《中國肌內(nèi)效貼技術(shù)臨床應(yīng)用專家共識》學(xué)習(xí)分享
- 高鈣血癥護理查房課件
- 《2024版 CSCO非小細胞肺癌診療指南》解讀
- 圍填海項目生態(tài)保護修復(fù)方案編制技術(shù)指南(試行)
- 2024年工業(yè)和信息化部應(yīng)急通信保障中心招聘高頻500題難、易錯點模擬試題附帶答案詳解
- 物體打擊傷亡事故應(yīng)急處置卡
- 2024-2030年中國飛機AFP和ATL復(fù)合材料行業(yè)市場發(fā)展趨勢與前景展望戰(zhàn)略分析報告
- 《祝?!饭_課一等獎創(chuàng)新教學(xué)設(shè)計 統(tǒng)編版高中語文必修下冊-1
評論
0/150
提交評論