计算机网络课程设计 实验报告.doc

上传人:rrsccc 文档编号:9005958 上传时间:2021-01-29 格式:DOC 页数:18 大小:293.50KB
返回 下载 相关 举报
计算机网络课程设计 实验报告.doc_第1页
第1页 / 共18页
计算机网络课程设计 实验报告.doc_第2页
第2页 / 共18页
计算机网络课程设计 实验报告.doc_第3页
第3页 / 共18页
计算机网络课程设计 实验报告.doc_第4页
第4页 / 共18页
计算机网络课程设计 实验报告.doc_第5页
第5页 / 共18页
点击查看更多>>
资源描述

《计算机网络课程设计 实验报告.doc》由会员分享,可在线阅读,更多相关《计算机网络课程设计 实验报告.doc(18页珍藏版)》请在三一文库上搜索。

1、计算机网络课程设计实验报告- CSMA/CD协议仿真学院:班级:学号:姓名:指导老师:周莲英0目 录一、课程设计目的2二、课程设计要求2三、相关知识21. CSMA/CD协议工作原理及性能分析22.以太帧的发送流程33.以太帧的接收流程3四、参考仿真程序4五、仿真说明及程序分析7六、sleep函数分析8七、协议的改进9八、心得体会10九、附录11一、课程设计目的以太网是目前应用最广泛的局域网。本课程设计的目的是通过模拟以太帧的发送过程,使大家能进一步理解和掌握以太网核心协议CSMA/CD。二、课程设计要求编写程序模拟以太结点的数据发送流程。具体要求:1) 用两个线程a和b模拟两台主机。2) 用

2、一个双字类型变量Bus来模拟总线(将其初始化为“0”,并且总线等于“0”时表示总线空闲)。3) 两个子线程向总线发送自己的数据。数据用该线程的线程号进行模拟,发送数据用线程号和Bus的“或”操作进行模拟(即BusBus|ID,ID为该线程的线程号)。4) 每台主机须向总线上成功发送10次数据,如果其中某次数据发送失败,则该线程结束。5) 发送流程须遵循CSMA/CD。随机延迟算法中的冲突窗口取0.005。在数据发送成功(即BusID)后,报告“ID send success”,产生冲突(Bus!ID)后报告“ID send conllision”,发送失败(即冲突计数器值为0)后报告“ID s

3、end failure”。随着主机发送成功次数增加,报告其已发送成功的次数,如“主机A发送成功数3”。三、相关知识1. CSMA/CD协议工作原理及性能分析以太网的核心技术是随机争用型介质访问控制方法,即带有冲突检测的载波侦听多路访问CSMA/CD方法。它的工作原理是: 发送数据前先侦听信道是否空闲,若空闲,则立即发送数据。若信道忙碌,则等待一段时间至信道中的信息传输结束后再发送数据;若在上一段信息发送结束后,同时有两个或两个以上的节点都提出发送请求,则判定为冲突。若侦听到冲突,则立即停止发送数据,等待一段随机时间,再重新尝试。 其原理简单总结为:先听后发,边发边听,冲突停发,随机延迟后重发。

4、性能指标:信道利用率、吞吐量、介质利用率等CSMACD的主要影响因素:传播时延、工作站数等。 CSMA/CD对站点个数不是很敏感,对实际的输入负载比较敏感。 CSMA/CD对传播时延a比较敏感。 CSMA/CD冲突不可避免。 CSMA/CD的介质利用率随a的上升下降较快。 CSMA/CD适合通信量不大,交互频繁的场合 对于CSMA/CD帧越长,吞吐量越太,要求帧具有最小长度,当有许多短消息时,带宽浪费严重。 CSMA/CD在轻负载时提供最短延迟,但对重负载敏感。(资料来源:百度百科http:/ 载波侦听过程。结点在发送一个帧前,必须侦听总线是否空闲。由于以太的数据采用曼彻斯特编码方式,所以可以

5、通过判断总线电平是否跳变来确定总线是否空闲。若总线空闲,就可启动发送,否则继续侦听。2) 冲突检测。在数据发送过程中,可能会产生冲突。所以在发送数据的过程中,也应该进行冲突检测,只要发现冲突就应该停止发送数据。3) 随机延迟后重发。在检测到冲突、停止发送后,结点进行随机延迟后重发。若重发16次后还没成功,则宣告发送失败,取消该帧的发送。随机延迟的计算方法一般采用截止二进制指数后退算法。该算法可表示为:T=2*R*a。其中T为结点重新发送需要的后退延迟时间,a为冲突窗口值,R为随机数,从0到2k1中取值,k的取值为min(n,10),n为该帧已被发送的次数,图1为以太帧的发送流程。3.以太帧的接

6、收流程帧接收流程大致可以分为以下三个步骤:1) 检查是否发生冲突,若发生冲突则丢弃该帧,若没有冲突,进入下一步。发送帧装配帧总线忙?启动发送冲突?发送完成?冲突加强冲突次数加1冲突多于16161516?发送失败败计算后退延迟等待后退延迟时间发送成功NNNN2) 检查该帧的目的地址看是否可以接收该帧,若可以接收,则进入下一步。3) 检查CRC校验和LLC数据长度。若都正确,接收该帧,否则丢弃。图1 以太网的发送过程四、参考仿真程序#include stdafx.h#include csmacd.h#include #include #include #include #ifdef _DEBUG

7、#define new1 DEBUG_NEW #undef THIS_FILE HIS_FILE=_FILE_; #endif /static char T CWinThread *thread1,*thread2; /定义变量 DWORD ID1,ID2,Bus=0; /初始化共享 UINT aThread(LPVOID pParam); /线程a,代表主机a UINT bThread(LPVOID pParam); /线程b,代表主机b using namespace std; int _tmain(int argc,TCHAR* argv,TCHAR*envp) int nRetCode

8、=0; if(!AfxWinInit(:GetModuleHandle(NULL),NULL, :GetCommandLine(),0) cout_T(Fata1 Error:MFC initialization failed)m_nThreadID; /获取线程ID号 thread2=AfxBeginThread(bThread,NULL); /启动线程b ID2=thread2-m_nThreadID; /获取线程ID号 getchar(); return nRetCode; UINT aThread(LPVOID pParam) /线程a(主机a) int i=0; /发送成功次数 in

9、t CollisionCounter=0; /冲突计数器初始值为16 double Collisionwindow=0.05; /冲突窗口值取0.05 int randNum=rand()%3; /随机数 可用Srand函数改变随机函数的种子,改善随机性Loop:if (Bus=0) /总线空闲 Bus=Bus|ID1; /模拟发包 Sleep(12); / 单位是毫秒 if(Bus=ID1) /无冲突,由发送方负责检测 printf(%d Send Successnn,ID1); /发送成功 Bus=0; /内存清零 CollisionCounter=0; /复原冲如计数器 Sleep(ra

10、nd()%10); / i+; printf(主机a发送成功次数=%dnn,i); if(i10) goto Loop; /发送次数不够10次,开始下一次发送 else printf(%d Send Collisionnn,ID1); /发生冲突 Bus=0; CollisionCounter+; /冲突计数器减1 if(CollisionCounter10)?10:CollisionCounter)*Collisionwindow);/ goto Loop; /下一次尝试发送 else printf(%ld Send Failurenn,ID1);/重发次数超过16次,宣布发送失败 else

11、 /总线忙 goto Loop; /继续载波侦听 return 0; UINT bThread(LPVOID pParam)/线程b int j=0; /发送成功次数 int CollisionCounter=0;/冲突计数器初始值为16 double CollisionWindow=0.05;/为争用期(51.2us),以时间为单位的冲突窗口 int randNum=rand()%3;/随机数 Loop: if(Bus=0)/总线空闲 Sleep(2); / 可用随机函数模拟其他用户随机接入 / Bus=Bus|ID2;/模拟发包 Sleep(3); / if(Bus=ID2)/无冲突 pr

12、intf(%d Send Successnn,ID2); /发送成功 Bus=0; /总线清零 CollisionCounter=0; /复原冲突计数器 Sleep(rand()%10); j+; printf(主机b发送成功次数=%dnn,j); if(j!=10) /不够10次开始下一次发送 goto Loop ; else printf(%d Send Collisionnn,ID2); Bus=0; CollisionCounter+; /冲突计数器减1 if(CollisionCounter10)?10:CollisionCounter)*CollisionWindow); goto

13、 Loop; else printf(%d Send Failurenn,ID2); else /总线忙 goto Loop; /继续装载波侦听 return 0; 注:程序在VC下编制、执行。五、仿真说明及程序分析1. 设计中的重点及难点1) 模拟冲突的过程,在这个程序中不要使用任何线程同步机制,以保证各线程执行的随机性;2) 若程序中不能模拟出冲突,可以在某些地方加入延时;3) 程序产生冲突主要取决于各线程能否交叉执行,具体又取决于CPU数、每一线程需要运行的时间等;2. 程序流程开 始启动线程A启动线程B结 束图2为主程序流程图。图 3为主程序中的线程流程图,其中线程A和线程B的线程相同

14、。图 2 主程序流程图开 始总线闲?发送数据BusBus|ID冲突?报告成功,Bus清零成功计数加1,报告成功次数复原冲突计数器成功计数器10?报告冲突,Bus清零冲突计数器1冲突计数器0?报告失败计算随机延迟时间并延迟结 束YYYY 图3 线程流程图六、sleep函数分析 对照第四项中参考仿真程序,按sleep使用顺序先后依次讨论:1 Sleep(12): 线程a发送时延为12ms,改变sleep函数参数来观察不同时延对碰撞的影响,有:时延(ms)运行5次,每次出现冲突的次数平均值2366364.812422222.41203333331200222222理论上分析传播及发送时延越大,冲突越

15、大,但实际运行结果不能反映。随着时延参数数量级的增加,一次程序运行的时间也明显增加,符合实际。但当时延达到几十秒时,显然不利于数据的高效传输。2 Sleep(rand()%10):确认一数据帧发送成功后随机等待一个不超过10ms的时间。此处是模拟的帧间隙,即发送成功后等待一帧间隙继续准备发送下一帧。考虑到CSMA/CD协议的帧间隙固定为9.6us,在改进后的程序(见附录)中此处改作Sleep(0.0096)。3 Sleep(randNum*(int)pow(2.0,(CollisionCounter10)?10:CollisionCounter)*Collisionwindow):检测到冲突、

16、停止发送后,结点进行随机延迟后重发。随机延迟采用截止二进制指数后退算法。该算法可表示为:T=2*R*a。其中T为结点重新发送需要的后退延迟时间,Collisionwindow为冲突窗口值a,randNum为随机数R,从0到2k1中取值,k的取值为min(n,10),CollisionCounter为该帧已被发送的次数n。4 Sleep(2):为避免a,b线程sleep设置完全一致(此时仿真结果为a,b交替发送,无冲突),b检测到总线空闲时,延时2ms进行发送。可用随机函数模拟其他用户随机接入,即改为:Sleep(rand()%x),减少冲突的几率。考虑到争用期为51.2ms,随机等待的时间不能

17、超过这一上限值。结果汇总如下:随机等待的时间x(ms)09050冲突次数均值(次)104可见,随机接入确实有助于减少冲突的几率。5 Sleep(3):模拟从发包到监测到信道忙之间的时间,按照CSMA/CD协议,争用期和检测到信道忙有着充要关系,于是在改进的程序中此处与的随机时间加起来和是一个时间51.2us。七、协议的改进1 增加窗口值 将0.05改为0.10,窗口值增大,冲突次数减少,所需时间也有所下降。2 增加用户数 初始设置增加:*thread3以及UINT cThread(LPVOID pParam); 应用进程增加: UINT cThread(LPVOID pParam)/线程c (

18、同线程b)。 图4是运行后的结果截图。3 改变发送策略 参考程序中的发送策略为“1坚持的CSMA”:线路忙,继续侦听;不忙时,立即发送;能提高信道利用率,但带来更大可能的冲突。改进后的程序采用“p坚持的CSMA”:线路忙,继续侦听;不忙时,根据p概率进行发送。多次运行发现,冲突的平均次数明显下降。4 改变侦听策略 参考程序中线路忙,继续侦听;改进后的程序采用线路忙,等待一段时间,再侦听的侦听策略。图4 增加一个线程后运行结果八、心得体会实验刚开始时,感觉摸不着头脑,一方面熟悉VC+的环境和语言,一方面温习CSMA/CD协议的大意和细节。第一个阶段,我试着改了一些参数,如sleep的时间参数、窗

19、口值等等,将运行结果统计后与之前比较,发现有的与书本、与实际结论较符合,但效果也有不明显甚至恰恰相反的(如第六节第点)。第二个阶段,添加第三个用户,并加入计时器记录三个线程各自发完数据所用的时间。改进后的程序实现了减少冲突和用时相差不大,但运行结果仍然体现出几点不足:一是三个用户随机接入的特性不明显,模拟的结果时常出现“a发完后b发,b发完后c发”的状况;二是三者用时每次运行波动很大。实验过程中产生的很多疑问,感谢老师和同学的悉心指导,才得以解决。九、附录改进后程序源代码及运行结果截图:#include stdafx.h#include csmacd.h#include time.h#incl

20、ude stdio.h#include stdlib.h#include #include #include #include #ifdef _DEBUG #define new1 DEBUG_NEW #undef THIS_FILE HIS_FILE=_FILE_; #endif CWinThread *thread1,*thread2,*thread3; /定义变量 DWORD ID1,ID2,ID3,Bus=0; /初始化共享 UINT aThread(LPVOID pParam); /线程a,代表主机a UINT bThread(LPVOID pParam); /线程b,代表主机b U

21、INT cThread(LPVOID pParam); /线程c,代表主机c double p=0.8; /改进发送策略:p坚持using namespace std; int _tmain(int argc,TCHAR* argv,TCHAR*envp) int nRetCode=0; if(!AfxWinInit(:GetModuleHandle(NULL),NULL, :GetCommandLine(),0) cout_T(Fata1 Error:MFC initialization failed)m_nThreadID; /获取线程ID号 thread2=AfxBeginThread(

22、bThread,NULL); /启动线程b ID2=thread2-m_nThreadID; /获取线程ID号 thread3=AfxBeginThread(cThread,NULL); /启动线程c ID3=thread3-m_nThreadID; /获取线程ID号 getchar(); return nRetCode; /*线程a*UINT aThread(LPVOID pParam) /线程a(主机a) clock_t start, finish; double duration; start = clock(); int i=0; /发送成功次数 double t,t1;t=0;t1=

23、0; int CollisionCounter=0; /冲突计数器初始值为0 double Collisionwindow=0.05; /冲突窗口值取0.05 /double Collisionwindow=0.10; int randNum=rand()%3; /随机数 可用Srand函数改变随机函数的种子,改善随机性。(用于二进制指数退避) Loop: /载波侦听 t=rand()%10000/10000; if (tp) if (Bus=0) /总线空闲 /边发送边检测 t1=rand()%10000/10000*0.0512; Sleep(t1); Bus=Bus|ID1;/模拟发包

24、Sleep(0.0512-t1); if(Bus=ID1) /无冲突,由发送方负责检测 printf(%d Send Successnn,ID1); /发送成功 Bus=0; /内存清零 CollisionCounter=0; /复原冲突计数器 Sleep(0.0096); / 模拟帧间隙 (发送成功后等待一帧间隙继续准备发送下一帧) i+; printf(主机a发送成功次数=%dnn,i); if(i10) goto Loop; /如果发送次数不够10次,则开始下一次发送 /(检测到冲突:立即中止发送、强化冲突、采用二进制指数退避算法重传) else printf(%d Send Colli

25、sionnn,ID1); /发生冲突 Bus=0; CollisionCounter+; /冲突计数器加一 if(CollisionCounter10)?10:CollisionCounter)*Collisionwindow); /二进制指数退避 goto Loop; /下一次尝试发送 else printf(%ld Send Failurenn,ID1);/重发次数超过16次,宣布发送失败 else /总线忙 Sleep(rand()%100/10); /在侦听策略所作的改进 goto Loop; finish = clock(); duration = (double)(finish -

26、 start) ; printf( A delays:%f msn, duration ); system(pause); return 0; /*线程b*/b与a原则上应该一样UINT bThread(LPVOID pParam)/线程b clock_t start, finish; double duration; start = clock(); int j=0; double t=0; double t1=0; /发送成功次数 int CollisionCounter=0; /冲突计数器初始值为0 double CollisionWindow=0.05; /为争用期(51.2us),以

27、时间为单位的冲突窗口 /double Collisionwindow=0.10; int randNum=rand()%3;/随机数 Loop: t=rand()%10000/10000; if (tp) if(Bus=0)/总线空闲 t1=rand()%10000/10000*0.0512/2; /单程时延 Sleep(t1); Bus=Bus|ID2;/模拟发包 Sleep(0.0512-t1); if(Bus=ID2)/无冲突 printf(%d Send Successnn,ID2); /发送成功 Bus=0; /总线清零 CollisionCounter=0; /复原冲突计数器 Sl

28、eep(0.0096); /等待一个帧间隙 j+; printf(主机b发送成功次数=%dnn,j); if(j!=10) /不够10次开始下一次发送 goto Loop ; else /有冲突 printf(%d Send Collisionnn,ID2); Bus=0; CollisionCounter+; /冲突计数器减1 if(CollisionCounter10)?10:CollisionCounter)*CollisionWindow); goto Loop; else /重发次数超过16次,宣布发送失败 printf(%d Send Failurenn,ID2); else /总

29、线忙 Sleep(rand()%100/10); /侦听策略所作的改进 goto Loop; finish = clock(); duration = (double)(finish - start) ; printf( B delays:%f msn, duration ); system(pause); return 0; /*线程c*UINT cThread(LPVOID pParam)/线程c clock_t start, finish; double duration; start = clock(); int j=0;double t=0;double t1=0; /发送成功次数

30、int CollisionCounter=0;/冲突计数器初始值为16 double CollisionWindow=0.05;/为争用期(51.2ms),以时间为单位的冲突窗口 int randNum=rand()%3;/随机数 Loop: t=rand()%10000/10000; if (tp) if(Bus=0)/总线空闲 t1=rand()%10000/10000*0.0512/2; Sleep(t1); /单程时延 Bus=Bus|ID3;/模拟发包 Sleep(0.0512-t1); if(Bus=ID3)/无冲突 printf(%d Send Successnn,ID3); /

31、发送成功 Bus=0; /总线清零 CollisionCounter=0; /复原冲突计数器 Sleep(rand()%10); j+; printf(主机c发送成功次数=%dnn,j); if(j!=10) /不够10次开始下一次发送 goto Loop ; else printf(%d Send Collisionnn,ID3); Bus=0; CollisionCounter+; /冲突计数器减1 if(CollisionCounter10)?10:CollisionCounter)*CollisionWindow); goto Loop; else printf(%d Send Failurenn,ID3); else /总线忙 Sleep(rand()%100/10); goto Loop; finish = clock();

展开阅读全文
相关资源
猜你喜欢
相关搜索

当前位置:首页 > 社会民生


经营许可证编号:宁ICP备18001539号-1