433X1《计算机网络原理》实验指导书Word格式文档下载.docx
《433X1《计算机网络原理》实验指导书Word格式文档下载.docx》由会员分享,可在线阅读,更多相关《433X1《计算机网络原理》实验指导书Word格式文档下载.docx(29页珍藏版)》请在冰豆网上搜索。
三、实验要求:
1.按照实验内容和步骤完成各个实验;
2.在实验报告中要有详细地实验步骤以及结果;
3.按时上交实验报告。
四、实验步骤
1.工程创建
在VC6中新建一个新工程,选择:
Win32ConsoleApplication,输入工程名。
具体方法:
启动VC6.0,单击【File】->
【New】,如图1所示;
图1
(1)服务器端创建:
然后在【新建工程】的对话框中的【Projects】选项卡中选择:
Win32ConsoleApplication,输入一个工程名及保存路径,点击【确定】,如图2所示;
图2
(2)客户端创建:
在【新建工程】的对话框中的【Projects】选项卡中选择:
MFCAppWizard[exe],输入一个工程名及保存路径,点击【确定】,选择“单文档模式”,完后确定完成,如图3所示,完成后新建一个主界面窗体,如图4所示。
图3
图4
2.Winsock初始化
在Windows环境下进行网络程序设计时,所有的Winsock函数都是从ws2_32.dll导出的,我们可以通过#pragmacomment(lib,"
ws2_32.lib"
)语句链接到该库文件。
但在使用Winsock函数之前还必须调用WSAStartup函数对库资源进行初始化工作,使用完毕后,在退出程序之前,我们还必须调用WSACleanup函数来释放库资源。
为了便于程序的设计,我们先设计一个CInitSock类来管理WinSock库。
在工程中添加新类的过程步骤如下:
1)在VC6.0环境中点击【insert】->
【newaclass】菜单;
2)在弹出的对话框中,选定classtype为GenericClass,在Name输入框中输入类的名称CInitSock,然后点击确定即可。
在InitSock.h和InitSock.cpp添加代码,详细代码如下所示。
////////////////////////////////////////////////////////////////////////////
//initSock.h//
#if!
defined(AFX_INITSOCK_H__70EFFE09_9598_4C98_A067_29100702ACE8__INCLUDED_)
#defineAFX_INITSOCK_H__70EFFE09_9598_4C98_A067_29100702ACE8__INCLUDED_
#if_MSC_VER>
1000
#pragmaonce
#endif//_MSC_VER>
#pragmacomment(lib,"
)
#include"
winsock2.h"
classCInitSock
{
public:
CInitSock();
virtual~CInitSock();
};
#endif//!
//////////////////////////////////////////////////////////////////////
//InitSock.cpp:
implementationoftheCInitSockclass.//
InitSock.h"
//Construction/Destruction
CInitSock:
:
CInitSock()
WSADATAwsaData;
WORDsockVersion=MAKEWORD(2,2);
if(:
WSAStartup(sockVersion,&
wsaData)!
=0)
exit(0);
}
~CInitSock()
:
WSACleanup();
然后在工程中新建一个.cpp的源文件,在这个源文件中填写主函数代码,并且在这个.cpp源文件的开始部分包含如下头文件:
”initSock.h”和”stdio.h”,还申明一个CInitSock类对象,具体代码可如下所示:
stdio.h"
CInitSockinitSock;
//初始化Winsock库,对库资源进行初始化工作,释放资源
3.编程模式
(1)服务器端:
函数具体说明请参考MSDN或者讲义或者教材。
1)创建socket
Socket函数的原型为:
SOCKETsocket(intfamily,inttype,intprotocol);
创建一个流式套接字可以如下所示:
SOCKET_socket=socket(AF_INET,SOCK_STREAM,0);
创建一个数据报式套接字可以如下所示:
SOCKET_socket=socket(AF_INET,SOCK_DGRAM,0);
注:
在面向TCP的应用中我们应该创建一个流式套接字。
2)绑定bind
bind函数的原型:
intbind(SOCKETsockfd,conststructsockaddr*myaddr,socklen_taddrlen)
绑定是将一个套接字和一个套接字地址绑定在一起,在调用bind之前还必须设定服务器地址。
如下可以设定一个服务器地址:
sockaddr_inserverAddress;
;
//定义地址结构体
serverAddress.sin_addr.S_un.S_addr=inet_addr("
192.168.1.107"
);
//服务器ip地址
serverAddress.sin_family=AF_INET;
serverAddress.sin_port=htons(6000);
//服务器端口,例如使用6000
下面的语句将套接字和地址serverAddress绑定在一起:
bind(sockSrv,(SOCKADDR*)&
serverAddress,sizeof(SOCKADDR));
htonl=hosttonetworklong,就是把主机的字节顺序转化成网络上的字节顺序,参数为longint型;
同理htons=hosttonetworkshort,只不过参数为shortint型。
地址族必须为AF_INET,端口为6000,绑定的ip地址也可以用INADDR_ANY代替,表示可以用本机的任何IP地址。
bind命令绑定本地刚才创建好的socket。
格式如上。
3)监听listen
listen函数的原型为:
intlisten(SOCKETsockfd,intqueue_length);
如下语句可以对一个套接字sockSrv进行监听:
listen(sockSrv,5);
4)接受连接accept,接收/发送数据send/recv
sockaddr_inaddrClient;
intlen=sizeof(SOCKADDR);
charsendBuf[]=“TCPServerDemo!
\r\n”;
SOCKETsockConnect=accept(sockSrv,(SOCKADDR*)&
addrClient,&
len);
//接受客户端连接
if(sockConnect==INVALD_SOCKET)//如果连接不成功
{
printf(“Failedaccept!
”);
continue;
printf("
接受到一个连接:
%s"
inet_ntoa(addrClient.sin_addr));
//显示客户端的IP
//关闭连接套接字,终止通信
closesocket(sockConnect);
inet_ntoa函数转换Internet网络地址为点分十进制格式。
5)发送/接收数据send/recv
send(sockConnect,sendBuf,strlen(sendBuf)+1,0);
//发送数据
recv(clientSocket,recvBuffer,strlen(recvBuffer),0);
//接收数据
6)关闭监听套接字,终止服务器
closesocket(sockSrv);
(2)客户端:
1)创建连接套接字
SOCKETclientSocket=socket(AF_INET,SOCK_STREAM,0);
2)设置通信地址
structsockaddr_inaddrSrv;
addrSrv.sin_addr.S_un.S_addr=inet_addr("
//表示连接服务器的IP
addrSrv.sin_family=AF_INET;
addrSrv.sin_port=htons(6000);
3)向服务器提出连接请求:
intcon;
con=connect(clientSocket,(SOCKADDR*)&
addrSrv,sizeof(SOCKADDR));
//连接服务器
if(con!
=0){
//连接服务器失败
cannotconnecttoserver\n"
return0;
4)连接成功后,接收服务器端发送来的信息
charrecvBuf[100];
intnRecv;
nRecv=recv(clientSocket,recvBuf,100,0);
//接收服务端的数据
if(nRecv>
0)
recvBuf[nRecv]=‘\0’;
接收到的数据:
%s\n"
recvBuf);
5)关闭套接字,终止通信
closesocket(sockClient);
4.项目简单演示
1)开启服务器端,等待客户端连接
2)开启客户端,可以开启多个,为了达到效果,可以再不同的机器上开启客户端
3)在客户端上点击“LINK”按钮,连接服务器。
4)开始聊天,只要连接上服务器的客户端都会收到聊天信息,相当于简单的群聊。
五、实验报告
1.完成本项目实验后,学生应提交实验报告。
2.实验报告格式与要求见附件。
实验2《NS2网络仿真实验》
1)学生能够初步掌握NS2网络模拟平台,并且能够利用网络模拟平台进行简单的实验。
2)学习采用距离矢量算法(DistanceVectorAlgorithm)的动态路由。
3)加深对TCP拥塞控制与流量控制机制的理解,并且能够为实验需要简单修改NS2的核心模块。
本实验分为三个实验过程,NS2平台的坏境搭建、NS2网络路由协议的仿真以及要简单修改NS2的核心模块。
此外,在实验过程中需要同学们自学linux操作系统的安装和使用(可在虚拟机中安装linux,本实验指导书使用的VMware虚拟机中的ubuntu操作系统),熟悉linux下的软件开发过程(如vi编辑器,gcc编译器),熟悉Tcl和Otcl脚本语言,熟悉C++编程语言。
三、实验要求
1.了解NS2的基本原理
2.熟悉Tcl和Otcl脚本语言
3.熟悉NS2的解不了模块
4.根据实验指导书搭好实验必需的坏境
1.NS2坏境搭建
(1)点击下载ns2的最新版本ns-allinone-2.35,并解压到对应目录下。
(也可以用命令解压:
tarzxfns-allinone-2.35.tar.gz如果想看解压的输出过程:
把"
zxf"
改为"
zxvf"
)。
例如:
$tarzxvfns-allinone-2.35.tar.gz(解压)
$sudomkdir/usr/local/ns2(建立空文件夹)
$sudomvns-allinone-2.35/usr/local/ns2(将ns2文件移动到新建的文件夹里)
$cd/usr/local/ns2/ns-allinone-2.35(转到ns2的文件夹中)
(2)下载并安装下一步ns-2.35时所必需的软件包:
$sudoapt-getinstallbuild-essential
$sudoapt-getinstalltcl8.4tcl8.4-devtk8.4tk8.4-dev
$sudoapt-getinstalllibxmu-dev
当用apt-get更新软件包时常出现错误提示Unabletolocatepackageupdate,解决方法是:
先更新apt-get
#sudoapt-getupdate
#sudoapt-getupgrade
(3)输入cd命令,转到ns-allinnone-2.35文件夹下,输入./install,进行安装。
按下回车键,同学们可以休息一会啦,这个过程大概需要5分钟左右(具体时间关乎机器的性能),5分钟之后大概出现如下提示:
(不要关闭终端)
Pleaseput/usr/local/ns-allinone-2.35/bin:
/usr/local/ns-allinone-2.35/tcl8.5.10/unix:
/usr/local/ns-allinone-2.35/tk8.5.10/unix
intoyourPATHenvironment;
sothatyou'
llbeabletorunitm/tclsh/wish/xgraph.
IMPORTANTNOTICES:
(1)YouMUSTput/usr/local/ns-allinone-2.35/otcl-1.14,/usr/local/ns-allinone-2.35/lib,
intoyourLD_LIBRARY_PATHenvironmentvariable.
IfitcomplainsaboutXlibraries,addpathtoyourXlibraries
intoLD_LIBRARY_PATH.
Ifyouareusingcsh,youcansetitlike:
setenvLD_LIBRARY_PATH<
paths>
Ifyouareusingsh,youcansetitlike:
exportLD_LIBRARY_PATH=<
(2)YouMUSTput/usr/local/ns-allinone-2.35/tcl8.5.10/libraryintoyourTCL_LIBRARYenvironmental
variable.Otherwisens/namwillcomplainduringstartup.
Afterthesesteps,youcannowrunthensvalidationsuitewith
cdns-2.35;
./validate
Fortroubleshooting,pleasefirstreadnsproblemspage
http:
//www.isi.edu/nsnam/ns/ns-problems.html.Alsosearchthensmailinglistarchive
forrelatedposts.
(4)设置环境变量
Linux环境中设置环境变量有三种方式,临时设置,当前用户设置,系统坏境变量设置。
在此处仅设置当前用户坏境变量。
具体步骤如下:
gedit打开/home/*user*/.bashrc,分别加入下面代码:
(*user*换成自己的相应目录)在.bashrc加入(根据安装完成后终端的提示来设置环境变量):
PATH="
$PATH:
/usr/local/ns-allinone-2.35/bin:
/usr/local/ns-allinone-2.35/tk8.5.10/unix"
LD_LIBRARY_PATH="
/usr/local/ns-allinone-2.35/otcl-1.14:
/usr/local/ns-allinone-2.35/lib"
TCL_LIBRARY="
/usr/local/ns-allinone-2.35/tcl8.5.10/library"
编辑完成,source/home/*user*/.bashrc(注意前提是要用root登陆,不然的话输入$sudo-s,以root角色登陆。
)source命令是把文件中的命令执行一次的意思。
(5)验证安装
在重启后的终端中输入ns命令,出现%,说明安装成功,如图所示:
2.NS2网络协议仿真
这个实验主要是观察链路状态发生变化时,使用静态路由和动态路由的差异性。
实验的结构如图1所示,节点n0会使用ftp将数据传送到n5,传送时间为0.1s~3.0s,在1.0s时,链路n1到n4发生问题,所以数据无法从n1到n4之间的链路传送。
在2.0s时,链路n1到n4问题解决,数据有可以从此路传送。
图1网络拓扑结构
TCL程序:
静态路由执行方法
1、运行TCl脚本
2、运行Nam程序,观察结果
(1)使用静态路由,传送数据从n0到n5的路径是n0----n1----n4---n5.如图2-1
图2-1图2-2
(2)在1.0s时,n1到n4链路发生问题,因为使用静态路由算法,路由表不会更新,所以数据无法发送到n4.如图2-2
(3)在3.0s时,n1到n4链路的问题得到解决,所以数据又按路径n0----n1----n4---n5传送到n5.如图2-3
图2-3
动态路由执行方式
1、运行TCL脚本
2、运行nam程序,观察结果
(1)因为使用动态路由方式,所以一开始,节点与节点之间必须互换信息,以建立路由表,如图3-1
图3-1图3-2
(2)路由表建立后,数据传送的路径是n0----n1----n4---n5.如图3-2
(3)在1.0s时,n1到n4链路发生问题,因为使用动态路由算法,所以节点互相通信,因此n0到n5数据发送的路径更新为n0----n1----n2---n3----n5.如图3-4
图3-3图3-4
(4)在3.0s时,n1到n4之间的链路恢复,节点互相通信后,路由表更新,因此n0到n5数据发送的路径也恢复为n0----n1---n4----n5.如图3-5
图3-4
3.修改NS2核心模块
(1)预设实验结果:
修改队列的丢包策略,当接收队列中未丢包,数据包正常入队列,一旦出现队列丢包现象,则暂停接受数据包,一直到队列为空再接受。
(2)在NS-2核心模块中找到队列的丢包模块(在ns-allinone-2.35/ns-2.35/queue路径下)
a.修改drop-tail.h文件,在类DropTail中添加一个布尔变量isdrop(初始值为false),用于判断队列是否已经发生丢包,再添加一个int型变量n(初始值为0)用于记录发生丢包时不接受包的个数。
b.在入队函数enque中,判断如下:
if(如果发生队列已满)
if(从队列头部丢包)
丢包;
else从队头丢包;
isdrop=true;
//添加代码,此时已丢包,isdrop置为真
else
if(isdrop)//添加代码,原先是队列未满则数据包入队,现在判断如果丢包了
{//则不接受数据包,并统计个数。
当不接受的个数=队列的长度时,
//又开始接受数据包
n++;
if(n>
=预设队列的长度)
{
n=0;
isdrop=false;
}
}
else
数据包入队;
//丢数据包入列
(3)修改drop-tail.cc函数enque,具体代码图2所示
(4)动画演示与验证
a.开始发生丢包,图3所示。
图3开始发生丢包
b.清空队列,把队列中的数据发送完再接受新的数据,图4所示。
图4清空队列
c.节点0停止发送数据包,如5所示。
图5节点0停止发送数据包
d.节点1停止发送数据包,如图5所示
图5节点1停止发送数据包
e.节点3停止发送数据,如图6所示,整个仿真也将结束。
图6节点3停止发送数据
f.通过实验演示得到了预期的实验结果,即一旦发生丢包后,节点会等到队列中的数据
发送完后才会接受新的数据包。
实验3《ip数据包捕获》