计算机网络实验报告_第1页
计算机网络实验报告_第2页
计算机网络实验报告_第3页
计算机网络实验报告_第4页
计算机网络实验报告_第5页
已阅读5页,还剩18页未读 继续免费阅读

下载本文档

版权说明:本文档由用户提供并上传,收益归属内容提供方,若内容存在侵权,请进行举报或认领

文档简介

1、计算机网络实验报告姓名:班级: 学号:实验日期:2011年12月1、题目:ARQ协议的模拟实现2、环境:在visual studio 环境下,采用c+程序设计语言,模拟实现ARQ协议。3、实验内容: p1模拟发送方:首先从界面读取待发送字符(每接受一个字符的输入),保存到文件file1.txt中,并启动计时器;p2模拟接收方,它从file1.txt中查找是否有新字符到来,并提供模拟界面给用户选择: 1. Ack-接收该字符 2. NAK-丢弃 3. 无反应-导致超时 将用户选择的结果记录到file2.txt中; 接收的字符保存到file3.txt 中;n p1等待接收方应答:读取file2.t

2、xt 决定下面的操作:n 如果是ACK,则继续接收用户输入;n 如果是NAK,则重传该字符;n 如果超时仍没有新的ACK或NAK,则重传该字符。n 注:file1.txt要发送的串, file2.txt保存中间结果, file3.txt接受的串,由实验者自己生成。4、实验步骤:(1)编写receiver()函数模拟接收端的相应处理过程;(2)编写sender()函数模拟发送端相应处理过程,其中sender函数调用了receiver()函数;(3)编写主函数main()函数,调用sender()和receiver()函数来实现整个发送接收过程,进而模拟了ARQ协议的实现。5、 实验中的问题及心得

3、:ARQ协议中,发送方每发送一个字符便要启动计时器,在规定时间内,若发送方未收到接收方返回的确认信息,则认为超时,需重发原字符。经过思考,我通过for循环反复读取file2文件实现了这一定时功能,而循环的次数则决定定时器的时间。此外还可利用c+语言自带的time()函数来实现计时功能。此外,为方便读取中间结果,file2文件的内容每次都会更新,并且采用简单的字符代表复杂的字符串,这些简化都使程序更加简洁,但并未影响整个模拟功能的实现。为了更加流畅地更新、利用文件中的数据,sender()函数调用了receiver()函数,以及时对文件数据进行接收端的相应处理,以供发送端使用。从而模拟实现整个发

4、送接收过程。6、 通过实验所掌握的内容通过此次试验,我对ARQ协议的原理以及基本工作过程有了更深入的理解、掌握。同时在一定程度上增强了我的独立编程能力和独立思考能力。越来越发现,编程其实没那么难,但想成为高手也很不容易。ARQ协议的模拟实现代码如下:#include #include #include /下面是两个函数原型void receiver(int ,fstream &,fstream &,ofstream &);/接收方void sender(fstream &datafile1,fstream &datafile2,ofstream &datafile3);/发送方void mai

5、n()fstream datafile1,datafile2;ofstream datafile3;cout下面开始数据的传输,注意:传输数据以“!”结束endl; sender(datafile1,datafile2,datafile3);cout数据传输结束endl;/接收端void receiver(int i,fstream &datafile1,fstream &datafile2,ofstream &datafile3)char r,re;datafile1.open(file1,ios:out|ios:in);if(!datafile1) cout文件打开失败!=A&r=Z)/若

6、读取的字符有效,即正确接受字符 datafile3.open(file3,ios:app); if(!datafile3) cout文件打开失败!endl; exit(0); datafile3r;/将收到的字符写入文件file3 cout字符已正确接收endl; cout准备发送确认信息ACKendl; cout请输入A,并以回车结束re; datafile2.open(file2,ios:out); if(!datafile2) cout文件打开失败!endl; exit(0); datafile2re;/将确认信息写入file2 if(rZ)/读取的字符无效,即接受字符出错 cout接收

7、字符错误endl; cout准备发送信息NAKendl; coutre; datafile3.open(file3); if(!datafile3) cout文件打开失败!endl; exit(0); datafile3re;/返回出错信息,将N写入file3 datafile1.close(); datafile2.close(); datafile3.close();/发送端void sender(fstream &datafile1,fstream &datafile2,ofstream &datafile3)char s,st;long i=0; cout整个信息输入以“!”结束;co

8、uts;datafile1.open(file1,ios:out|ios:in);if(!datafile1)cout文件打开失败!endl;exit(0);datafile1s;/发送信息,即将待发送的字符写入文件file1 i+;cout字符已被发送endl;datafile1.close();receiver(i,datafile1,datafile2,datafile3);/调用接收端进行相应操作while(1)if(s=!)break;for(int t=1;t=4;t+)/起定时器的作用datafile2.open(file2,ios:in);if(!datafile2) cout

9、文件打开失败!endl; exit(0);datafile2.get(st);datafile2.close(); if(st=A)/发送方收到接收方的确认信息ACK cout上一个字符已被接收!endl; couts; datafile1.open(file1,ios:out|ios:in); if(!datafile1) cout文件打开失败!endl; exit(0); datafile1s;/将新的待发送字符写入file1 i+; cout字符已被发送endl; datafile1.close();receiver(i,datafile1,datafile2,datafile3);/调

10、用接收端进行相应操作 break; if(st=N)/发送方收到接收方的出错信息NAK cout上一个字符出错!endl; cout现在需重新发送原字符endl; datafile1.open(file1,ios:out|ios:in); if(!datafile1) cout文件打开失败!endl; exit(0);datafile1s; i+; cout字符已被发送endl; datafile1.close(); receiver(i,datafile1,datafile2,datafile3);/调用接收端进行相应操作 break; cout定时器超时,现重新发送原字符。endl; da

11、tafile1.open(file1,ios:out|ios:in); if(!datafile1) cout文件打开失败!endl; exit(0);datafile1s; i+; cout字符已被发送endl; datafile1.close(); receiver(i,datafile1,datafile2,datafile3);/调用接收端进行相应操作RIP协议实验一:实验目的通过交互实验和编程实验,深入理解RIP协议的工作原理,了解RIP协议分组接收和发送流程以及路由表的维护,进一步掌握计算机网络的核心技术路由技术,培养路由协议编程开发能力。二:实验原理三:实验过程以及代码解释实验代

12、码:#include sysinclude.h#include extern void rip_sendIpPkt(unsigned char* pData, UINT16 len, unsigned short dstPort, UINT8 iNo);/*RIP包的发送函数*/extern struct stud_rip_route_node *g_rip_route_table;/*路由表*/typedef struct _packet_header /*RIP数据包的头部*/unsigned char command;/*命令只能是REQUEST或者RESONSE*/unsigned c

13、har version;/*版本号,1或者2*/unsigned short pad0;/*置零*/ packet_header;typedef struct _packet_data/*RIP数据包*/unsigned short addrfamily;/*地址族,必须为2*/unsigned short routetag;/*路由标记*/unsigned int ipaddr;/*IP地址*/unsigned int netmask;/*掩码*/unsigned int nexthop;/*下一跳*/unsigned int metric;/*跳数*/ packet_data;#defin

14、e DECLAREERROR(pkt,type) printf(Discard because %dn,type);ip_DiscardPkt(pkt,type);return 0;/*定义RIP包出错时的返回类型*/unsigned char buffer256;/*缓冲区*/void dumpPkt(unsigned char*buf,int len)/*实现数据提取功能*/printf(Dump sending packet:n);int l=0;for (int i=0;iif_no=iNo|pnow-metric=16)pnow=pnow-next;/*遍历并复制路由链表*/do/*

15、组装RIP数据包的头部*/packet_header*ph=(packet_header*)buffer;ph-command=2; /*响应(RESPONSE)分组*/ph-version=version; /*版本号*/ph-pad0=0; /*必须为0*/*组装数据包*/int pCount=0;while (pCountaddrfamily=htons(2); pd-routetag=0; pd-ipaddr=htonl(pnow-dest);if (version=2)pd-netmask=htonl(pnow-mask);elsepd-netmask=0;if (version=2

16、)pd-nexthop=htonl(pnow-nexthop);elsepd-nexthop=0;pd-metric=htonl(pnow-metric);pCount+;do pnow=pnow-next; while (pnow&(pnow-if_no=iNo|pnow-metric=16);/*发送数据包*/dumpPkt(buffer,sizeof(packet_header)+sizeof(packet_data)*pCount);rip_sendIpPkt(buffer,sizeof(packet_header)+sizeof(packet_data)*pCount,520,iNo

17、); while (pnow);#include char*clone(char*org,int len)/*取出数据并删除缓冲区的原始数据*/char*t=(char*)malloc(len);memmove(t,org,len);return t;int stud_rip_packet_recv(char*pBuffer, int bufferSize, UINT8 iNo, UINT32 srcAdd)pBuffer=clone(pBuffer,bufferSize);/*检查数据包头部是否合法,否则调用出错函数返回出错类型*/packet_header*ph=(packet_heade

18、r*)pBuffer;if (ph-command!=1&ph-command!=2) DECLAREERROR(pBuffer,STUD_RIP_TEST_COMMAND_ERROR);if (ph-version!=1&ph-version!=2) DECLAREERROR(pBuffer,STUD_RIP_TEST_VERSION_ERROR);if (ph-pad0!=0) DECLAREERROR(pBuffer,STUD_RIP_TEST_COMMAND_ERROR);if (ph-command=1)/*为REQUEST包*/printf(Get valid requestn);

19、MakePacket(ph-version,iNo);else/*为RESPONSE包*/dumpPkt(unsigned char*)pBuffer,bufferSize);/*从缓冲区取出数据组包*/int snums=(bufferSize-sizeof(packet_header)/sizeof(packet_data);/*计算缓冲区RIP包的总数*/for (int i=0;iipaddr=ntohl(pd-ipaddr);pd-netmask=ntohl(pd-netmask);pd-nexthop=ntohl(pd-nexthop);pd-metric=ntohl(pd-met

20、ric);/*给RIP链表里的每一项赋值*/stud_rip_route_node*hd=g_rip_route_table;printf(offset: %d, ip: %08x, mask: %08x, nh: %08x, metric: %08x, if: %xn,(int)pd)-(int)buffer,pd-ipaddr,pd-netmask,pd-nexthop,pd-metric,iNo);dumpPkt(unsigned char*)pd,sizeof(packet_data);int hdcount=0;while (hd) if (hd-dest=pd-ipaddr&hd-

21、mask=pd-netmask) break;/*实现水平分割*/hd=hd-next;hdcount+;do/*对传来的RIP数据进行分析,更新本地路由表*/if (hd) /*如果下一跳不是原来表中的下一跳,只有当跳数更低时,更新表项*/printf(Match at %d and nexthop %xn,hdcount,hd-nexthop);if (hd-nexthop!=pd-nexthop)if (hd-metricpd-metric)hd-metric=pd-metric+1;/*跳数加一*/hd-nexthop=pd-nexthop;/*目的地更新*/hd-if_no=iNo;

22、break;/*如果下一跳满足,直接更新RIP链表*/hd-metric=pd-metric+1;hd-nexthop=pd-nexthop;hd-if_no=iNo;/*如果跳数为16显然不合法,大于16的置为16*/if (hd-metric16)hd-metric=16;else /*如果不存在则创建新节点(链表)*/printf(Unmatch.n);if (pd-metric=16) break;/*跳过跳数为16的项目*/stud_rip_route_node* nhd=(stud_rip_route_node*)malloc(sizeof(stud_rip_route_node)

23、;/*创建新节点*/nhd-dest=pd-ipaddr;nhd-mask=pd-netmask;nhd-nexthop=pd-nexthop;nhd-metric=pd-metric+1;/*初始值为1*/nhd-if_no=iNo;nhd-next=g_rip_route_table;/*插入路由链表的头部*/g_rip_route_table=nhd; while (false);/*超时处理函数*/void stud_rip_route_timeout(UINT32 destAdd, UINT32 mask, unsigned char msgType)if (msgType=RIP_

24、MSG_SEND_ROUTE)/*向两个端口都广播自己的路由表*/MakePacket(2,1);MakePacket(2,2);else if (msgType=RIP_MSG_DELE_ROUTE)stud_rip_route_node*hd=g_rip_route_table;while (hd) if (hd-dest=destAdd&hd-mask=mask)break;hd=hd-next;/*传入超时的路由表项,将跳数置为16,此时该表项会被自动删除*/hd-metric=16;FTP协议实验报告l 实验目的1、在Linux系统上完成一个文件传输协议(FTP)的简单实现。2、深入

25、理解FTP协议的原理和协议细节。3、学会利用Socket接口设计实现简单应用层协议。4、掌握TCP/IP网络应用程序的基本设计方法和实现技巧。l 实验原理1、FTP协议2、socket编程(1)什么是Socket(2)Socket的建立(3)Socket配置 (4)连接建立(5)结束传输l 实验内容在Linux系统上使用Socket接口实现FTP客户端 和服务器的程序,使客户端可以连接至服务器,并且可以进行一些FTP的基本操作,如列出目录、下载文件等。从FTP协议的实现角度来看,客户端 与服务器的命令通道和数据通道需要分享,同时应该支持以下一些FTP命令:get:取远方的一个文件。put:传给

26、远方一个文件。pwd:显示远方当前目录。dir:列出远方当前目录。cd:改变远方当前目录。?:显示你提供的命令quit:退出返回l 实验过程1、实现服务器端(1)全局变量为了记录缓冲区大小、当前目录、当前工作路径、帮助信息而定义了以下几个全局变量: #define dataLen 1024 /缓冲区大小char currentDirPath200; /当前工作目录的绝对路径char currentDirName30; /当前目录的名称char help=getget a file from servernputupload a file to servernpwddisplay the cur

27、rent directory of serverndirdisplay the files in the current directory of serverncdchange the directory of servern?display the whole command which equals helpnquit returnn; /帮助信息(2)函数在服务器端实现了以下几个函数:char *getDirName(char *dirPathName); /根据当前工作目录的绝对路径得到当前目录名称void cmd_pwd(int sock); /处理pwd命令void cmd_di

28、r(int sock); /处理dir命令void cmd_cd(int sock,char *dirName); /处理cd命令void cmd_help(int sock); /处理?命令void cmd_get(int sock,char*fileName); /处理get命令void cmd_put(int sock,char *fileName); /处理put命令(3)主函数的实现:先建立数据通道和命令通道,然后监听,若有客户端连上,则建立一个子进程,先向客户端发送帮助信息,然后根据客户端的命令来调用上述各函数来处理。int main(int argc,char *argv)int

29、 sock; /服务器用于监听的数据通道int sockmsg; /服务器用于监听的命令通道 char client_cmd10; /客户端出发的命令char cmd_arg20; /客户端输入的文件或目录名,用在cd,put,get命令中struct sockaddr_in server; /服务器数据通道的信息struct sockaddr_in servermsg; /服务器命令通道的信息int datasock; /用于通信的数据通道int msgsock; /用于通信的命令通道pid_t child; /client子进程sock=socket(AF_INET,SOCK_STREAM

30、,0); /创建用于传数据的套接字 sockmsg=socket(AF_INET,SOCK_STREAM,0); /创建用于传消息的套接字 int opt = 1,opt2 = 1; setsockopt(sock , SOL_SOCKET , SO_REUSEADDR , &opt , sizeof(opt); /实现sock的重用 setsockopt(sockmsg , SOL_SOCKET , SO_REUSEADDR , &opt2 , sizeof(opt2);/实现sockmsg的重用 if (sock 0 | sockmsg 0) /socket创建失败 perror(open

31、ing stream socket); exit(1); memset(&server,0,sizeof(server);server.sin_family=AF_INET; /设置协议族server.sin_addr.s_addr=htonl(INADDR_ANY); /监听所有地址server.sin_port=htons(45000); /端口设为45000memset(&servermsg,0,sizeof(servermsg);servermsg.sin_family=AF_INET; /设置协议族servermsg.sin_addr.s_addr=htonl(INADDR_ANY)

32、; /监听所有地址servermsg.sin_port=htons(45001); /端口设为45001 if (bind(sock,(struct sockaddr *) &server,sizeof(server) 0 | bind(sockmsg,(struct sockaddr *) &servermsg,sizeof(servermsg) 0)/连接不成功perror(binding stream socket);exit(1); int length = sizeof(server);int lengthmsg = sizeof(servermsg);if (getsockname

33、(sock,(struct sockaddr *) &server,&length) 0 | getsockname(sockmsg,(struct sockaddr *) &servermsg,&lengthmsg) 0)/得到套接字的本地名字perror(getting socket name);exit(1);printf(Socket port # %d %dn,ntohs(server.sin_port),ntohs(servermsg.sin_port);memset(currentDirPath,0,sizeof(currentDirPath);getcwd(currentDir

34、Path,sizeof(currentDirPath);/将当前工作目录的绝对路径复制到/currentDirPath中listen(sock,2); /监听数据通道listen(sockmsg,2); /监听命令通道while(1)datasock = accept(sock,(struct sockaddr*)0,(int*)0); /与客户端的数据通道连接msgsock = accept(sockmsg,(struct sockaddr*)0,(int*)0); /与客户端的命令通道连接if (datasock = -1 | msgsock=-1)perror(accept);elsei

35、f(child = fork() = -1) /出错printf(Fork Error!n);if(child = 0) /子进程printf(connection accepted! new client comingn);write(datasock,help,strlen(help) + 1);loop:memset(client_cmd,0,sizeof(client_cmd);int rval = 0;rval = read(msgsock,client_cmd,sizeof(client_cmd);/读命令printf(%dn,rval);if(rval = 0;i -) /找到最

36、后一个/号,之后的字符串即为当前工作目录名称if(dirPathNamei = /) pos=i;break;dirName = (char *)malloc(len - pos + 1);for(i = pos + 1;i = len;i +)dirNamei - pos - 1 = dirPathNamei;return dirName;(5)void cmd_pwd(int sock)的实现:调用getDirName函数来得到当前工作目录名称,然后发到客户端void cmd_pwd(int sock)int len; char *savePointer = getDirName(currentDirPath); /得到当前工作目录名称strcpy(currentDirName,savePointer);len = strlen(currentDirName) + 1;wri

温馨提示

  • 1. 本站所有资源如无特殊说明,都需要本地电脑安装OFFICE2007和PDF阅读器。图纸软件为CAD,CAXA,PROE,UG,SolidWorks等.压缩文件请下载最新的WinRAR软件解压。
  • 2. 本站的文档不包含任何第三方提供的附件图纸等,如果需要附件,请联系上传者。文件的所有权益归上传用户所有。
  • 3. 本站RAR压缩包中若带图纸,网页内容里面会有图纸预览,若没有图纸预览就没有图纸。
  • 4. 未经权益所有人同意不得将文件中的内容挪作商业或盈利用途。
  • 5. 人人文库网仅提供信息存储空间,仅对用户上传内容的表现方式做保护处理,对用户上传分享的文档内容本身不做任何修改或编辑,并不能对任何下载内容负责。
  • 6. 下载文件中如有侵权或不适当内容,请与我们联系,我们立即纠正。
  • 7. 本站不保证下载资源的准确性、安全性和完整性, 同时也不承担用户因使用这些下载资源对自己和他人造成任何形式的伤害或损失。

评论

0/150

提交评论