滑動(dòng)窗口協(xié)議仿真_第1頁(yè)
滑動(dòng)窗口協(xié)議仿真_第2頁(yè)
滑動(dòng)窗口協(xié)議仿真_第3頁(yè)
滑動(dòng)窗口協(xié)議仿真_第4頁(yè)
滑動(dòng)窗口協(xié)議仿真_第5頁(yè)
已閱讀5頁(yè),還剩24頁(yè)未讀 繼續(xù)免費(fèi)閱讀

下載本文檔

版權(quán)說(shuō)明:本文檔由用戶提供并上傳,收益歸屬內(nèi)容提供方,若內(nèi)容存在侵權(quán),請(qǐng)進(jìn)行舉報(bào)或認(rèn)領(lǐng)

文檔簡(jiǎn)介

1、滁州學(xué)院課程設(shè)計(jì)報(bào)告課程名稱: 計(jì)算機(jī)網(wǎng)絡(luò) 設(shè)計(jì)題目: 滑動(dòng)窗口協(xié)議仿真 系 別: 計(jì)算機(jī)與信息工程學(xué)院 專 業(yè): 計(jì)算機(jī)科學(xué)與技術(shù) 組 別: 第五組 起止日期: 2011年11月24日2011年12月7日指導(dǎo)教師: 趙國(guó)柱 計(jì)算機(jī)與信息工程學(xué)院二一一年制課程設(shè)計(jì)題目滑動(dòng)窗口協(xié)議仿真組長(zhǎng)趙育坤學(xué)號(hào)2011220135班級(jí)計(jì)專1班系別計(jì)算機(jī)與信息工程學(xué)院專業(yè)計(jì)算機(jī)科學(xué)與技術(shù)組員閆婷、張俠、余靜、于東鋒、張飛、趙育坤指導(dǎo)教師趙國(guó)柱課程設(shè)計(jì)目的掌握滑動(dòng)窗口協(xié)議的基本原理,并能夠用所學(xué)計(jì)算機(jī)高級(jí)語(yǔ)言進(jìn)行編程模擬課程設(shè)計(jì)所需環(huán)境開(kāi)發(fā)環(huán)境: VC+ 運(yùn)行環(huán)境:Windows 操作系統(tǒng)課程設(shè)計(jì)任務(wù)

2、要求1程序按照滑動(dòng)窗口協(xié)議實(shí)現(xiàn)端對(duì)端的數(shù)據(jù)傳送。包括協(xié)議的各種策略,如包丟失、停等應(yīng)答、超時(shí)等都應(yīng)有所仿真實(shí)現(xiàn)2顯示數(shù)據(jù)傳送過(guò)程中的各項(xiàng)具體數(shù)據(jù)。雙方幀的個(gè)數(shù)變化,幀序號(hào),發(fā)送和接受速度,暫?;蛑貍魈崾镜日n程設(shè)計(jì)工作進(jìn)度計(jì)劃序號(hào)起止日期工 作 內(nèi) 容分工情況111月24號(hào)11月27號(hào)了解工作要求,明確分工內(nèi)容,網(wǎng)上查閱相關(guān)資料所有組員共同參與211月28號(hào)11月30號(hào)sender隊(duì)列模塊的編寫(xiě)由閆婷完成312月1號(hào)12月4號(hào)sender主函數(shù)的編寫(xiě)由趙育坤、張飛完成411月28號(hào)11月30號(hào)receiver隊(duì)列模塊的編寫(xiě)由張俠完成512月1號(hào)12月4號(hào)receiver主函數(shù)的編寫(xiě)由余靜、于東鋒

3、完成612月5號(hào)12月7號(hào)最后匯總,調(diào)試由趙育坤、于東鋒完成指導(dǎo)教師簽字: 年 月 日教研室審核意見(jiàn):教研室主任簽字: 年 月 日課程設(shè)計(jì)任務(wù)書(shū)一. 引言二. 基本原理2.1 窗口機(jī)制2.2 1bit滑動(dòng)窗口協(xié)議2.3 后退N協(xié)議2.4 選擇重傳協(xié)議2.5 流量控制三. 需求分析3.1 課程設(shè)計(jì)題目3.2 開(kāi)發(fā)環(huán)境3.3 運(yùn)行環(huán)境3.4 課程設(shè)計(jì)任務(wù)及要求3.5 界面要求3.6 網(wǎng)絡(luò)接口要求四. 詳細(xì)設(shè)計(jì) 4.1 結(jié)構(gòu)體的定義4.2 發(fā)送方的主要函數(shù)4.3 接受方的主要函數(shù)五. 源代碼 5.1 發(fā)送方的主要代碼5.2 接收方的主要代碼六. 調(diào)試與操作說(shuō)明 致謝參考文獻(xiàn) 課程設(shè)計(jì)的主要內(nèi)容1.引

4、言早期的網(wǎng)絡(luò)通信中,通信雙方不會(huì)考慮網(wǎng)絡(luò)的擁擠情況直接發(fā)送數(shù)據(jù)。由于大家不知道網(wǎng)絡(luò)擁塞狀況,一起發(fā)送數(shù)據(jù),導(dǎo)致中間結(jié)點(diǎn)阻塞掉包,誰(shuí)也發(fā)不了數(shù)據(jù)。在數(shù)據(jù)傳輸過(guò)程中,我們總是希望數(shù)據(jù)傳輸?shù)母煲恍?,但如果發(fā)送方把數(shù)據(jù)發(fā)送的過(guò)快,接收方就可能來(lái)不及接收,這就造成數(shù)據(jù)的丟失。因此就有了滑動(dòng)窗口機(jī)制來(lái)解決這些問(wèn)題。早期我們使用的是1bit滑動(dòng)窗口協(xié)議,一次只發(fā)送一個(gè)幀,等收到ack確認(rèn)才發(fā)下一個(gè)幀,這樣對(duì)信道的利用率太低了。因此提出了一種采用累積確認(rèn)的連續(xù)ARQ協(xié)議,接收方不必對(duì)收到的幀逐個(gè)發(fā)送ack確認(rèn),而是收到幾個(gè)幀后,對(duì)按序到達(dá)的最后一個(gè)幀發(fā)送ack確認(rèn)。同1bit滑動(dòng)窗口協(xié)議相比,大大減少了ac

5、k數(shù)量,并消除了延遲ack對(duì)傳輸效率的影響。2.基本原理2.1 窗口機(jī)制滑動(dòng)窗口協(xié)議的基本原理就是在任意時(shí)刻,發(fā)送方都維持了一個(gè)連續(xù)的允許發(fā)送的幀的序號(hào),稱為發(fā)送窗口;同時(shí),接收方也維持了一個(gè)連續(xù)的允許接收的幀的序號(hào),稱為接收窗口。發(fā)送窗口和接收窗口的序號(hào)的上下界不一定要一樣,甚至大小也可以不同。不同的滑動(dòng)窗口協(xié)議窗口大小一般不同。發(fā)送方窗口內(nèi)的序號(hào)代表了那些已經(jīng)被發(fā)送,但是還沒(méi)有被確認(rèn)的幀,或者是那些可以被發(fā)送的幀。接受方為其窗口內(nèi)的每一個(gè)序號(hào)保留了一個(gè)緩沖區(qū)。與每個(gè)緩沖區(qū)相關(guān)聯(lián)的還有一位,用來(lái)指明該緩沖區(qū)是滿的還是空的。 2.2 1bit滑動(dòng)窗口協(xié)議當(dāng)發(fā)送窗口和接收窗口的大小固定為1時(shí),滑

6、動(dòng)窗口協(xié)議退化為停等協(xié)議(stopandwait)。該協(xié)議規(guī)定發(fā)送方每發(fā)送一幀后就要停下來(lái),等待接收方已正確接收的確認(rèn)(acknowledgement)返回后才能繼續(xù)發(fā)送下一幀。由于接收方需要判斷接收到的幀是新發(fā)的幀還是重新發(fā)送的幀,因此發(fā)送方要為每一個(gè)幀加一個(gè)序號(hào)。由于停等協(xié)議規(guī)定只有一幀完全發(fā)送成功后才能發(fā)送新的幀,因而只用一比特來(lái)編號(hào)就夠了。其發(fā)送方和接收方運(yùn)行的流程圖如圖所示。2.3 后退N協(xié)議由于停等協(xié)議要為每一個(gè)幀進(jìn)行確認(rèn)后才繼續(xù)發(fā)送下一幀,大大降低了信道利用率,因此又提出了后退n協(xié)議。后退n協(xié)議中,發(fā)送方在發(fā)完一個(gè)數(shù)據(jù)幀后,不停下來(lái)等待應(yīng)答幀,而是連續(xù)發(fā)送若干個(gè)數(shù)據(jù)幀,即使在連續(xù)

7、發(fā)送過(guò)程中收到了接收方發(fā)來(lái)的應(yīng)答幀,也可以繼續(xù)發(fā)送。且發(fā)送方在每發(fā)送完一個(gè)數(shù)據(jù)幀時(shí)都要設(shè)置超時(shí)定時(shí)器。只要在所設(shè)置的超時(shí)時(shí)間內(nèi)仍收到確認(rèn)幀,就要重發(fā)相應(yīng)的數(shù)據(jù)幀。如:當(dāng)發(fā)送方發(fā)送了N個(gè)幀后,若發(fā)現(xiàn)該N幀的前一個(gè)幀在計(jì)時(shí)器超時(shí)后仍未返回其確認(rèn)信息,則該幀被判為出錯(cuò)或丟失,此時(shí)發(fā)送方就不得不重新發(fā)送出錯(cuò)幀及其后的N幀。從這里不難看出,后退n協(xié)議一方面因連續(xù)發(fā)送數(shù)據(jù)幀而提高了效率,但另一方面,在重傳時(shí)又必須把原來(lái)已正確傳送過(guò)的數(shù)據(jù)幀進(jìn)行重傳(僅因這些數(shù)據(jù)幀之前有一個(gè)數(shù)據(jù)幀出了錯(cuò)),這種做法又使傳送效率降低。由此可見(jiàn),若傳輸信道的傳輸質(zhì)量很差因而誤碼率較大時(shí),連續(xù)測(cè)協(xié)議不一定優(yōu)于停止等待協(xié)議。此協(xié)議中

8、的發(fā)送窗口的大小為k,接收窗口仍是1。2.4 選擇重傳協(xié)議在后退n協(xié)議中,接收方若發(fā)現(xiàn)錯(cuò)誤幀就不再接收后續(xù)的幀,即使是正確到達(dá)的幀,這顯然是一種浪費(fèi)。另一種效率更高的策略是當(dāng)接收方發(fā)現(xiàn)某幀出錯(cuò)后,其后繼續(xù)送來(lái)的正確的幀雖然不能立即遞交給接收方的高層,但接收方仍可收下來(lái),存放在一個(gè)緩沖區(qū)中,同時(shí)要求發(fā)送方重新傳送出錯(cuò)的那一幀。一旦收到重新傳來(lái)的幀后,就可以原已存于緩沖區(qū)中的其余幀一并按正確的順序遞交高層。這種方法稱為選擇重發(fā)(SELECTICE REPEAT),其工作過(guò)程如圖所示。顯然,選擇重發(fā)減少了浪費(fèi),但要求接收方有足夠大的緩沖區(qū)空間。2.5 流量控制TCP的特點(diǎn)之一是提供體積可變的滑動(dòng)窗口

9、機(jī)制,支持端到端的流量控制。TCP的窗口以字節(jié)為單位進(jìn)行調(diào)整,以適應(yīng)接收方的處理能力。處理過(guò)程如下: (1)TCP連接階段,雙方協(xié)商窗口尺寸,同時(shí)接收方預(yù)留數(shù)據(jù)緩存區(qū); (2)發(fā)送方根據(jù)協(xié)商的結(jié)果,發(fā)送符合窗口尺寸的數(shù)據(jù)字節(jié)流,并等待對(duì)方的確認(rèn); (3)發(fā)送方根據(jù)確認(rèn)信息,改變窗口的尺寸,增加或者減少發(fā)送未得到確認(rèn)的字節(jié)流中的字節(jié)數(shù)。調(diào)整過(guò)程包括:如果出現(xiàn)發(fā)送擁塞,發(fā)送窗口縮小為原來(lái)的一半,同時(shí)將超時(shí)重傳的時(shí)間間隔擴(kuò)大一倍。(4)滑動(dòng)窗口機(jī)制為端到端設(shè)備間的數(shù)據(jù)傳輸提供了可靠的流量控制機(jī)制。然而,它只能在源端設(shè)備和目的端設(shè)備起作用,當(dāng)網(wǎng)絡(luò)中間設(shè)備(例如路由器等)發(fā)生擁塞時(shí),滑動(dòng)窗口機(jī)制將不起作

10、用。3.需求分析3.1 課程設(shè)計(jì)題目:滑動(dòng)窗口協(xié)議仿真3.2 開(kāi)發(fā)環(huán)境:Visual C+ 6.0 3.3 運(yùn)行環(huán)境:Windows 操作系統(tǒng) 3.4 課程設(shè)計(jì)任務(wù)及要求: (1)程序按照滑動(dòng)窗口協(xié)議實(shí)現(xiàn)端對(duì)端的數(shù)據(jù)傳送。包括協(xié)議的各種策略,如包丟失、停等應(yīng)答、超時(shí)等都應(yīng)有所仿真實(shí)現(xiàn)。 (2)顯示數(shù)據(jù)傳送過(guò)程中的各項(xiàng)具體數(shù)據(jù)。雙方幀的個(gè)數(shù)變化,幀序號(hào),發(fā)送和接受速度,暫?;蛑貍魈崾镜?。3.5 界面要求:此次課程設(shè)計(jì)要求的所有功能應(yīng)可視,我們組主要是用VC+編寫(xiě)的,運(yùn)行在DOS環(huán)境下,觀察發(fā)送方(sender)發(fā)送數(shù)據(jù)包到接收方(receive)時(shí)。3.6 網(wǎng)絡(luò)接口要求:兩臺(tái)機(jī)器或是一臺(tái)機(jī)器中兩

11、個(gè)獨(dú)立的線程模擬發(fā)送方與接受方,接收數(shù)據(jù)的端口初始應(yīng)為監(jiān)聽(tīng)狀態(tài)。發(fā)送方向接受方發(fā)起連接,成功后開(kāi)始發(fā)送數(shù)據(jù)。4.概要設(shè)計(jì)4.1 結(jié)構(gòu)體定義如下:typedef enum data = 1,ack,nak,tout frame_kind; /幀類型typedef struct frame_head frame_kind kind; /幀類型 unsigned int seq; /序列號(hào) unsigned int ack; /確認(rèn)號(hào) unsigned char dataMAX_LENGTH; /數(shù)據(jù)Head;typedef struct frame frame_head head; /幀頭 uns

12、igned int size; /數(shù)據(jù)的大小 Frame; typedef struct framenode /隊(duì)列節(jié)點(diǎn)類型 frame head_data; struct framenode *next; Framenode;typedef struct Framenode *front; /隊(duì)頭指針 Framenode *rear; /隊(duì)尾指針 LinkQueue;4.2 發(fā)送方的主要函數(shù)實(shí)現(xiàn):函數(shù)名:void InitLine(LinkQueue *q);功 能:初始化隊(duì)列。函數(shù)名:void GetFrameFromHost(LinkQueue *q);功 能:從主機(jī)取數(shù)據(jù)幀,由于實(shí)驗(yàn)需

13、要,假設(shè)主機(jī)有足夠多的數(shù)據(jù)幀要發(fā)送。void DeLine(LinkQueue *q);功 能:數(shù)據(jù)幀發(fā)送完畢(收到確認(rèn)幀)后,刪除發(fā)送的數(shù)據(jù)幀(隊(duì)頭)。函數(shù)名:int QueueEmpty(LinkQueue *q);功 能:判斷隊(duì)列是否為空。函數(shù)名:frame QueueFront(LinkQueue *q);功 能:取隊(duì)頭,首幀是準(zhǔn)備好待發(fā)送的幀。函數(shù)名:int QueueLen(LinkQueue *q);功 能:計(jì)算隊(duì)列長(zhǎng)度。函數(shù)名:DWORD WINAPI ReceiveFun(LPVOID pArg);功 能:發(fā)送線程調(diào)用的函數(shù),pArg參數(shù)存接收幀指針。函數(shù)名:void mai

14、n();功 能:發(fā)送方主函數(shù),首先和接收方(本機(jī)"127.0.0.1")建立socket連接并初始化發(fā)送隊(duì)列。然后重復(fù)下面的步驟:(1)從主機(jī)取數(shù)據(jù)幀;(2)發(fā)送數(shù)據(jù)幀,含超時(shí)重發(fā)(接收方未收到或未收到接收方ack)和錯(cuò)誤重發(fā)(收到接收方nak);(3)設(shè)置超時(shí)計(jì)時(shí)器,這里是5秒;(4)等待確認(rèn),調(diào)用CreateThread()函數(shù)創(chuàng)建一個(gè)線程,超時(shí)則調(diào)用TerminateThread()函數(shù)結(jié)束線程并再次發(fā)送數(shù)據(jù)幀。收到數(shù)據(jù)幀則做后續(xù)處理;(5)收到否認(rèn)幀nak則再次發(fā)送數(shù)據(jù)幀,收到確認(rèn)幀ack則發(fā)送下一個(gè)數(shù)據(jù)幀;(6)如果發(fā)送的測(cè)試時(shí)間達(dá)到20秒,則提示是否繼續(xù)測(cè)試,按

15、q或Q退出測(cè)試。4.3接收方的主要函數(shù)實(shí)現(xiàn):函數(shù)名:void InitLine(LinkQueue *q);功 能:初始化隊(duì)列。函數(shù)名:void GetFrameFromHost(LinkQueue *q);功 能:準(zhǔn)備好接收幀的緩沖池,首幀是待接收的幀,尾幀是已經(jīng)接收的待提交主機(jī)的幀。由于實(shí)驗(yàn)需要,假設(shè)數(shù)據(jù)幀送往主機(jī)是足夠快的。int DeLine(LinkQueue *q, frame *pf, unsigned int curw)功 能:將幀數(shù)據(jù)保存供提交主機(jī),curw是打開(kāi)的待接收數(shù)據(jù)的窗口。函數(shù)名:int QueueEmpty(LinkQueue *q);功 能:判斷隊(duì)列是否為空。函

16、數(shù)名:int QueueLen(LinkQueue *q);功 能:計(jì)算隊(duì)列長(zhǎng)度。函數(shù)名:void main();功 能:接收方主函數(shù),首先和發(fā)送方建立socket連接并初始化初始化接收窗口。然后重復(fù)下面的步驟:(1)等待,接收數(shù)據(jù)幀;(2)校驗(yàn)數(shù)據(jù)幀,假定產(chǎn)生隨機(jī)結(jié)果,20%的概率校驗(yàn)錯(cuò)誤或發(fā)送方發(fā)送數(shù)據(jù)幀超時(shí);(3)校驗(yàn)錯(cuò)誤時(shí),丟棄數(shù)據(jù)幀,并發(fā)送否認(rèn)幀nak;(4)如果出現(xiàn)接收超時(shí)(假定未收到發(fā)送方發(fā)送的數(shù)據(jù)幀),則不給發(fā)送發(fā)任何回應(yīng);(5)如果校驗(yàn)正確,首先判斷是否是上一幀的重發(fā)。是上一幀的重發(fā),則丟棄數(shù)據(jù)幀,并發(fā)送確認(rèn)幀ack;是新的數(shù)據(jù)幀,則保存數(shù)據(jù)幀到當(dāng)前接收窗口,并發(fā)送確認(rèn)幀ac

17、k。(6)送數(shù)據(jù)幀至主機(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 *q) if (QueueEmpty(q) printf("隊(duì)列為空!n"); Sleep(SLEEPMS); exit(0); return q->front->h

18、ead_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) >= MAXPOOL) printf("data %d 已準(zhǔn)備好n", q->front->head_data.head.seq);return;Framenod

19、e *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; / 幀大小隨機(jī)生成memset(p->head_data.head.data, '1', p->head_data.size);p->head_data.head.ack = -1;p->head_data.head.kind = da

20、ta;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->rear =p;printf("從主機(jī)得到:data %d,放入緩存n", p->head_data.head.seq);GetFrameFromHos

21、t(q); / 由于實(shí)驗(yàn)需要,假設(shè)主機(jī)有足夠多的數(shù)據(jù)幀要發(fā)送void DeLine(LinkQueue *q)Framenode *p = NULL;if(QueueEmpty(q)printf("隊(duì)列為空!n");else p = q->front;q->front = p->next;if (q->rear = p) q->rear = NULL;printf("發(fā)送data %d, %d 成功!從緩存中刪除n", p->head_data.head.seq, p->head_data.size);free(

22、p);p = NULL;void main() printf("建立連接 . n");Begin:WORD wVersionRequested; WSADATA wsaData; /初始化socket庫(kù)wVersionRequested=MAKEWORD(1,1); /兩個(gè)byte型合并成一個(gè)WORD型int err=WSAStartup(wVersionRequested,&wsaData);if(err!=0) Sleep(SLEEPMS); return; if ( LOBYTE( wsaData.wVersion ) != 1 | HIBYTE( wsaDa

23、ta.wVersion ) != 1 ) WSACleanup(); /中止Windows Sockets服務(wù) WSAStartup()成對(duì)使用Sleep(SLEEPMS); return; socketClient = socket(AF_INET,SOCK_STREAM,0);/監(jiān)聽(tīng)的套接字SOCKADDR_IN clientadd; clientadd.sin_addr.S_un.S_addr = inet_addr("127.0.0.1"); clientadd.sin_family = AF_INET; clientadd.sin_port = htons(700

24、1);/設(shè)置連接端的IP、端口if(SOCKET_ERROR=connect(socketClient,(SOCKADDR*)&clientadd,sizeof(SOCKADDR) ) /連接WSACleanup();Sleep(SLEEPMS);goto Begin;char getDataRECEIVE_MAX_LENGTH;memset(getData, 0, RECEIVE_MAX_LENGTH); /清零if(recv(socketClient,getData,RECEIVE_MAX_LENGTH,0) = SOCKET_ERROR) /接受 printf("接受連

25、接提示信息出錯(cuò)!n"); else printf("%sn",getData); char sendDataSEND_MAX_LENGTH;memset(sendData, 0, SEND_MAX_LENGTH); strcpy(sendData, "你好接收方,我是發(fā)送方!");if( SOCKET_ERROR = send(socketClient,sendData,strlen(sendData)+1,0) ) /發(fā)送 printf("發(fā)送連接提示信息出錯(cuò)!n");WSACleanup();closesocket(so

26、cketClient);Sleep(SLEEPMS); return; printf("按任意鍵繼續(xù)!n");while (!kbhit() ; /等待開(kāi)始Sleep(SLEEPMS);printf("1bit滑動(dòng)窗口協(xié)議:發(fā)送方,發(fā)送窗口=1n");LinkQueue QueueQ;InitLine(&QueueQ);frame packetsend; /dataframe packetreceive; / ack,nakunsigned long tick = GetTickCount(); int ret = 0;HANDLE hThrea

27、d; while(1)GetFrameFromHost(&QueueQ);/從主機(jī)取數(shù)據(jù)幀memset(&packetsend, 0, sizeof(packetsend);Sleep(SLEEPMS);printf("n");packetsend = QueueFront(&QueueQ); /取數(shù)據(jù)幀ret = send(socketClient, (char *)&packetsend, sizeof(packetsend), 0);/發(fā)送dataif(ret = SOCKET_ERROR)printf("發(fā)送數(shù)據(jù)出錯(cuò)!n&q

28、uot;); continue; printf("發(fā)送數(shù)據(jù)幀:data %d, %dn", packetsend.head.seq, packetsend.size);const unsigned long timeOut = 5 * 1000; /設(shè)置超時(shí)計(jì)時(shí)器 5秒超時(shí)memset(&packetreceive, 0, sizeof(packetreceive);Sleep(SLEEPMS);printf("n");InitializeCriticalSection(&gCS); / 初始化臨界區(qū) hThread=CreateThre

29、ad(NULL, 0, ReceiveFun, (LPVOID)&packetreceive, 0, NULL); int r = WaitForMultipleObjects(1, &hThread, TRUE, timeOut);DeleteCriticalSection(&gCS); /與InitializeCriticalSection(&gCS);成對(duì)使用if(ret = SOCKET_ERROR | ret = SOCKET_DISCONN)printf("接受出錯(cuò)!Press any key to continuen"); wh

30、ile (!kbhit() ; continue; if(r = WSA_WAIT_TIMEOUT) /判斷超時(shí)TerminateThread(hThread, 0); /終止線程printf("超時(shí)重傳:data %d, %dn", packetsend.head.seq,packetsend.size); else if(packetsend.head.seq = packetreceive.head.ack)srand(unsigned)time(NULL);switch(rand() % 5) /假定產(chǎn)生隨機(jī)結(jié)果,20%的概率超時(shí)case 0:printf(&quo

31、t;接收方發(fā)送回復(fù)超時(shí)(ack丟失模擬):%dn", packetsend.head.seq);printf("超時(shí)重傳:data %d, %dn", packetsend.head.seq,packetsend.size);break;default:if(packetreceive.head.kind = ack) printf("接受ack幀:ack %dn", packetreceive.head.ack);DeLine(&QueueQ);else if(packetreceive.head.kind = nak)printf(

32、"接受nak幀:nak %dn", packetsend.head.seq);break;else printf("幀序號(hào)出錯(cuò): %dn", packetreceive.head.ack);if(GetTickCount() - tick > 20 * TIMEOUT) /設(shè)置時(shí)間20秒printf("持續(xù)時(shí)間20s. 按q退出,其他鍵繼續(xù)n"); int kbc = getch();if(kbc = 'q' | kbc = 'Q')break;printf("按任意鍵退出!n"

33、;); while (!kbhit() ; Sleep(SLEEPMS);printf("謝謝使用!n");WSACleanup();closesocket(socketClient);Sleep(SLEEPMS);DWORD WINAPI ReceiveFun(LPVOID pArg) EnterCriticalSection(&gCS);/進(jìn)入critical sectionframe *packetreceive = (frame *)pArg;ret = recv(socketClient, (char *)packetreceive, sizeof(*pa

34、cketreceive), 0);LeaveCriticalSection(&gCS);/線程用畢,離開(kāi)critical sectionreturn ret; 5.2 接收方的主要代碼:void InitLine(LinkQueue *q)q->front = q->rear = NULL;int QueueEmpty(LinkQueue *q)return q->front = NULL && q->rear = NULL;frame QueueFront(LinkQueue *q)if (QueueEmpty(q) printf("

35、隊(duì)列為空!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;int GetFrameFromHost(LinkQueue *q)if(QueueLen(q) >= MAXPOOL)printf("準(zhǔn)備接受:data %

36、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, MAX_LENGTH);p->head_data.head.ack = -1;p->head_data.head.kind = ack;p->head_data.head.seq = 0;p->next =NULL;if(

37、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 GetFrameFromHost(q);int DeLine(LinkQueue *q, frame *pf, unsigned int curw) /假設(shè)數(shù)據(jù)幀送往主機(jī)是足夠快的Framenode *p = NULL;if(curw = q->front-&g

38、t;head_data.head.seq) p = q->front;elsep = q->rear;if(p->head_data.head.ack != -1) /假定數(shù)據(jù)已經(jīng)提交主機(jī)printf("向主機(jī)交付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->

39、;size); p->head_data.size = pf->size;p->head_data.head.ack = pf->head.seq; /保存發(fā)送幀序號(hào)return p->head_data.head.seq;frame QueueAnswer(LinkQueue *q, unsigned int curw)if(curw = q->front->head_data.head.seq) return q->front->head_data;elsereturn q->rear->head_data;void mai

40、n()Begin: WORD wVersionRequested; WSADATA wsaData; /初始化socket庫(kù) wVersionRequested = MAKEWORD( 1, 1 ); /兩個(gè)byte型合并成一個(gè)WORD型 int err = WSAStartup(wVersionRequested, &wsaData );/使用sockets之前要調(diào)用一次if ( err != 0 ) Sleep(SLEEPMS); return; if ( LOBYTE( wsaData.wVersion ) != 1 | HIBYTE( wsaData.wVersion ) !=

41、 1 ) WSACleanup();/中止Windows Sockets服務(wù) WSAStartup()成對(duì)使用Sleep(SLEEPMS); return; SOCKET socksrv = socket(AF_INET,SOCK_STREAM,0);/監(jiān)聽(tīng)的套接字 SOCKADDR_IN socketadd; socketadd.sin_addr.S_un.S_addr = htonl(INADDR_ANY); /監(jiān)聽(tīng)連接 socketadd.sin_family = AF_INET; socketadd.sin_port = htons(7001); /設(shè)置端口if( SOCKET_ERR

42、OR = bind(socksrv,(SOCKADDR*)&socketadd,sizeof(SOCKADDR) ) printf("綁定出錯(cuò)!n");WSACleanup();Sleep(SLEEPMS); return; if( SOCKET_ERROR = listen(socksrv,5) ) printf("監(jiān)聽(tīng)出錯(cuò)!");WSACleanup();Sleep(SLEEPMS); return; SOCKADDR_IN sockclient; int len = sizeof(SOCKADDR); SOCKET sockconn = a

43、ccept(socksrv,(SOCKADDR*)&sockclient,&len);/建立連接的套節(jié)字 if(INVALID_SOCKET = sockconn ) printf("建立連接出錯(cuò)!n"); return; char sendDataSEND_MAX_LENGTH;memset(sendData, 0, SEND_MAX_LENGTH); sprintf(sendData,"%s","你好發(fā)送方,我是接受方!"); if( SOCKET_ERROR = send(sockconn,sendData,st

44、rlen(sendData)+1,0) ) printf("發(fā)送連接提示信息出錯(cuò)!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滑動(dòng)窗口協(xié)議:接收方,接收窗口=1n&q

45、uot;);LinkQueue QueueQ;InitLine(&QueueQ);frame packetreceive; /dataframe packetsend; / ack,nakint curw = GetFrameFromHost(&QueueQ);/初始化接收窗口int ret = 0;while(1)memset(&packetreceive, 0, sizeof(packetreceive);Sleep(SLEEPMS);printf("n");ret = recv(sockconn,(char *)&packetrecei

46、ve, sizeof(packetreceive), 0);if(ret = SOCKET_ERROR | ret = SOCKET_DISCONN)if(ret = SOCKET_ERROR)printf("連接出錯(cuò)!自動(dòng)連接!n"); continue;elseprintf("連接已斷開(kāi),按q退出,其他鍵等待新的連接n"); int kbc = getch();if(kbc = 'q' | kbc = 'Q')break;else WSACleanup();closesocket(sockconn);Sleep(SLE

47、EPMS);goto Begin;srand(unsigned)time(NULL);switch(rand() % 5) /假定產(chǎn)生隨機(jī)結(jié)果,20%的概率校驗(yàn)錯(cuò)誤或接收發(fā)送方超時(shí)case 0:printf("接受數(shù)據(jù)幀:data %d, %d,校驗(yàn)錯(cuò)誤,丟棄(數(shù)據(jù)幀出錯(cuò)模擬)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("發(fā)送否認(rèn)幀:nak %dn", packetreceive.head.seq);break;case 1:packetsend.head.kind = tout; printf("發(fā)送方發(fā)送數(shù)據(jù)超時(shí)(數(shù)據(jù)幀丟失模擬)

溫馨提示

  • 1. 本站所有資源如無(wú)特殊說(shuō)明,都需要本地電腦安裝OFFICE2007和PDF閱讀器。圖紙軟件為CAD,CAXA,PROE,UG,SolidWorks等.壓縮文件請(qǐng)下載最新的WinRAR軟件解壓。
  • 2. 本站的文檔不包含任何第三方提供的附件圖紙等,如果需要附件,請(qǐng)聯(lián)系上傳者。文件的所有權(quán)益歸上傳用戶所有。
  • 3. 本站RAR壓縮包中若帶圖紙,網(wǎng)頁(yè)內(nèi)容里面會(huì)有圖紙預(yù)覽,若沒(méi)有圖紙預(yù)覽就沒(méi)有圖紙。
  • 4. 未經(jīng)權(quán)益所有人同意不得將文件中的內(nèi)容挪作商業(yè)或盈利用途。
  • 5. 人人文庫(kù)網(wǎng)僅提供信息存儲(chǔ)空間,僅對(duì)用戶上傳內(nèi)容的表現(xiàn)方式做保護(hù)處理,對(duì)用戶上傳分享的文檔內(nèi)容本身不做任何修改或編輯,并不能對(duì)任何下載內(nèi)容負(fù)責(zé)。
  • 6. 下載文件中如有侵權(quán)或不適當(dāng)內(nèi)容,請(qǐng)與我們聯(lián)系,我們立即糾正。
  • 7. 本站不保證下載資源的準(zhǔn)確性、安全性和完整性, 同時(shí)也不承擔(dān)用戶因使用這些下載資源對(duì)自己和他人造成任何形式的傷害或損失。

最新文檔

評(píng)論

0/150

提交評(píng)論