计算机网络课程设计题目一
-------解析IP数据包
1 课程设计目的
本课程设计的目的就是设计一个解析IP数据包的程序,并根据这个程序,说明IP 数据包的结构及IP协议的相关问题,从而对IP层的工作原理有更好的理解和认识。
2 课程设的要求
本设计的目标是捕获网络中的IP数据包,解析数据包的内容,将结果显示在标准输出上,并同时写入日志文件。
程序的具体要求如下:
1)以命令行形式运行:ipparse logfile,其中ipparse是程序名,而logfile则代表记录结果的日志文件。
2)在标准输出和日志文件中写入捕获的IP包的版本、头长度、服务类型、数据包总长度、数据包标识、分段标志、分段偏移值、生存时间、上层协议类型、头校验和、源IP地址和目的IP地址等内容。
3)当程序接收到键盘输入Ctrl+c时退出。
3 相关知识
互联网络层是TCP/IP协议参考模型中的关键部分。IP协议把传输层送来的消息组装成IP数据包,并把IP数据包传递给数据链路层。IP协议在TCP/IP协议族中处于核心地位,IP协议制定了统一的IP数据包格式,以消除各通信子网间的差异,从而为信息发送方和接收方提供了透明的传输通道。编制本程序前,首先要对IP包的格式有一定的了解,图7-1给出了IP协议的数据包格式。
IP数据包的第一个字段是版本宇段,其长度为4位,表示所使用的IP协议的版本。目前的版本是iPv4,版本字段的值为4,下一代的版本是IPv6,版本字段的值为6。本程序主要针对版本值为4的IP数据包的解析。
报头标长(IHL)字段为4位,它定义了以4B为一个单位的IP包的报头长度。报头中除了选项字段和填充域字段外,其他各字段是定长的。因此,IP数据包的头长度在20-40B之间,是可变的。
3)将累加的结果取反码,就是头校验和。
当收到一个IP包时,要检查报头是否出错,就把报头中的所有数据以16位为单位进行累加,若累加的结果为0,则报头没有出错。
地址字段包括源地址和目的地址。源地址和目的地址的长度都是32位,分别表示
发送数据包的源主机和目的主机的IP地址。
选项字段的长度范围是0—40BYTE,主要用于控制和测试。在使用选项字段的过程中,有可能出现报头部分的长度不是32位的整数倍的情况。如果出现这种情况,就需要通过填充位来凑齐。
4课程设计分析
为了获取网络中的IP数据包,必须对网卡进行编程,在这里我们使用套接字(socket)进行编程。但是,在通常情况下,网络通信的套接字程序只能响应与自己硬件地址相匹配的数据包或是以广播形式发出的数据包。对于其他形式的数据包,如已到达网络接口但却不是发送到此地址的数据包,网络接口在验证投递地址并非自身地址之后将不引起响应,也就是说应用程序无法收取与自己无关的数据包。我们要想获取流经网络设备的所有数据包,就需要将网卡设置为混杂模式。
本程序主要由三部分构成:初始化原始套接字,反复监听捕获数据包和解析数据包。下面就结合核心代码对程序的具体实现进行讲解,同时使程序流程更加清晰,去掉了错误检查等保护性代码。
1.使用原始套接字
套接字分为3种,即流套接字(Stream Socket)、数据报套接字(Datagram Socket)和原始套接字(Raw Socket)。要进行IP层数据包的接收和发送,应使用原始套接字。创建原始套接字的代码如下:
SOCKET sock;
sock=WSASoccket(AF_INET,SOCK_RAW,IPPROTO_IP,NULL,0,WSA FLAG OVERLAPPED);
在WSASoccket函数中,第一个参数指定通信发生的区字段,AF_INET是针对Internet的,允许在远程主机之间通信。第二个参数是套接字的类型,在AF_INET地址族下,有SOCK_STREAM、SOCK DGRAM,SOCK_RAW三种套接字类型。在这里,我们设置为SOCK RAW,表示我们声明的是一个原始套接字类型。第三个参数依赖于第二个参数,用于指定套接宇所用的特定协议,这里使用IP协议。第四个参数为WSAPROTOCOL_INFO位,该位可以置空。第五个参数保留,永远置0。第六个参数是标志位,WSA_FLAG_OVERLAPPED表明可以使用发送接收超时设置,本课程设计也可以把这个标志位设置为NULL,因为本设计不用考虑超时情况。
创建原始套接字后,IP头就会包含在接收的数据中。然后,我们可以设置IP头操作选项,调用setsockopt函数。其中flag设置为true,并设定IP HDRINCL选项,表明用户可以亲自对IP头进行处理。
BOOL flag=true;
setsockopt(sock,IPPROTO_IP,IP_HDRINCL,(char*)&flag,sizeof(flag));
之后,使用如下代码完成对socket的初始化工作:
/*获取主机名。/
char hostName[128):
gethostname(hostName,100);
/*获取本地IP地址*/
hostent * pHostIP;
pHostIP=gethostbyname(hostName);
/*填充SOCKADDR_IN结构的内容*/
sockaddr_in addr_in;
addr_in.sin_addr=*(in_addr *)pHostIP->h_addr_list[0];
addr_in.sin_family=AF_INET;
addr_in.sin_port=htons(6000);
/*绑定socket*/
bind(sock,(PSOCKADDR)&addr_in,sizeof(addr_in));
填写sockaddr_in的内容时,其地址值应填写为本机IP地址,本机IP地址可以通过gethostbyname()函数获取;端口号可以随便填写,但不能与系统冲突;协议族应填为AF_INET。注意,sockaddr_in结构的值必须是以网络字节顺序表示的值,而不能直接使用本机字节顺序的值。使用htons()函数可以将无符号短整型(unsigned short)的主机数据转换为网络字节顺序的数据。最后使用bind()函数将socket绑定到本地网卡上。
绑定网卡后,需要用WSAIoctl()函数把网卡设置为混杂模式,使网卡能够接收所有网络数据,其关键代码如下:
#define SIO_RCV ALL _WSAIOW(IOC_VENUOR,1)
DWORD dwBufferLen[10];
DWORD dwBufferInLen=1;
DWORD dwBytesReturned=0;
WSAIoctl(SnifferSOcket,IO_RCV AL,&dwBufferInLen,sizeof(dwBufferInLen),&dwBufferLen,sizeof(dwBufferLen),&dwBytesReturned,NULL,NULL);
如果接收的数据包中的协议类型和定义的原始套接字匹配,那么接收到的数据就拷贝到套接字中。因此,网卡就可以接收所有经过的IP包。
2.接收数据包
在程序中可使用recv()函数接收经过的IP包。该函数有四个参数,第一个参数接收操作所用的套接宇描述符;第二个参数接收缓冲区的地址;第三个参数接收缓冲区的大小,也就是所要接收的字节数;第四个参数是—个附加标志,如果对所发送的数据没特殊要求,直接设为0。因为IP数据包的最大长度是65535B,因此,缓冲区的大小不
能小于65535B。设置缓冲区后,可利用循环来反复监听接收IP包,用recv()函数实现接收功能的代码如下:
#define BUFFERSIZE 65535
char buffer[BUFFElSIZE)J //设置缓冲区
while(true)
{
recv(sock,buffer,BUFFElSIZE,O);//接收数据包
/*然后是解析接收的IP包*/
……………….
}
3.定义IP头部的数据结构
程序需要定义—个数据结构表示IP头部。这个数据结构应该和图7-1吻合,其代码如下:
typedef struct_IP_HEADER //定义IP头
{
union
{
BYTE Version;//版本(前4位)
BYTE HdrLen;//报头标长(后4位), IP头的长度);
};
BYTE ServiceType;//服务类型
WORD TotalLen;//总长度
WORD ID;//标识
union
{
WORD Flags;//标志(前3位)
WORD Fragoff ;//分段偏移(后13位)
);
BYTE TimeToLive;//生命期
BYTE Protocol;//协议
WORD HdrChksum;//头校验和
DWORD SrcAddr;//源地址
DWORD DstAddr;//目的地址
BYTE Options;//选项
}IP_HEADER;
这里我们只考虑IP头部结构,不考虑数据部分。在捕获IP数据包后,可以通过指针把缓冲区的内容强制转化为IP_HEADER数据结构。
IP_HEADER ip=*(IP_EEADER *) buffer;
4.IP包的解析
解析IP包的字段有两种策略。针对长度为8位、16位和31位的字段(或子宇段)时,可以利用IP_HEADER的成员直接获取。要解析长度不是8位倍数的字段(或子字段)时,可以利用C语言中的移位以及与、或操作完成。下面给出了通过IP_HEADER解析IP头各个字段的代码。
/*获取版本字段*/
ip.Version>>4;Array/*获取头部长度字段·/
ip.HdrLen & 0xof;
/*获取服务类型字段中的优先级子域?/
ip.ServlceType>>5;
/*获取服务类型字段中的TOS子域·/
(ip.ServiceType>>1)&0xOf;
/*获取总长度字段·/
ip.TotalLen;
/*获取标识字段*/
ip.ID;
/*解析标志字段*/
DF=(iP.Flags>>14)& 0x01:
MF=(ip.Flags>>13)& 0x01;
/*获取分段偏移字段。/
ip.FragOff & 0x1fff;
/od(取生存时间字段·/
ip.TimeToLive;
/*获取协议字段·/
ip.Protocol;
/*获取头校验和字段·/
ip.HdrChksum;
/*解析源IP地址字段*/
inet_ntoa(*(in addr*)& ip.SrcAddr;
/·解析目的IP地址字段*/
inet_ntoa(*(in_addr*)& ip.DstAddr)
5.参考程序流程图
图7-4给出—·个供参考的程序流程图。
7.5 相关扩展
本课程设计也可以利用winpcap完成,部分核心代码的简略提示如下。
1)获取所有存在的网络设备的链表。
Pcap_if_t *alldevs; //网络设备结构链表
Char errbuf[PCAP_ERRBUF_SIZE];//错误信息
/*所有网络设备的信息以链表形式保存在alldevs中*/
pcap_findalldevs(&alldevs,errbuf);
2)从链表中选择物理Ethernet卡后,用混杂模式打开,调用的函数为:
pcap_open_live(const char device,int snapeln,int promice,
int to_ms,char*errbuf)。
在这个函数中,第一个参数为要打开的设备名称,这里是Ethernet卡,可以从设备链表alldevs中选出。第二个参数应为捕获的数据包长度,添入65535以保证在链路层的整个数据包都被捕获。第三个参数为打开模式,填入1表明用混杂模式打开网卡。最后两个参数为读入超时时间和保存错误信息。
3)编译,设置过滤器
char packet_filter[]=”ip”;
pcap_compile(adhandle,&fcode,packet_filter,1,netmask);//编译过滤器
pcap_setfilter(adhandle,&fcode);
adhandle 参数为网卡描述符,fcode参数是一个BPF伪汇编程序,packet_filer参数用于设置的过滤规则,在这里我们只需要捕获IP包;
4)可利用pcap_loop函数捕获数据包。对于捕获的数据包,去掉数据链路层的14B的头部后才是真正的IP包信息。利用winpcap编程和利用socket编程在处理IP包上并没有太大区别。
计算机网络课程设计题目二
-------模拟Ethenet帧的发送过程
1课程设计目的
局域网技术发展十分迅速,目前已在企业,机关,学校的信息管理与信息服务领域中得到了广泛的应用。在早期,人们将局域网归为一种数据通信网络。随着局域网体系结构和协议标准研究的进展。操作系统的发展以及光纤技术的引入,局域网技术得到了快速发展。目前,Ethernet是应用最广泛的局域网。因此,学习Ethernet技术对深入掌握局域网知识是非常重要的。本课程设计的目的是模拟Ethernet帧的发送过程,使读者熟悉Ethernet帧的数据发送流程,即CSMA/CD工作流程。
2课程设计要求
编写程序模拟Ethernet结点的数据发送流程.具体要求:
1)用两个线程a和b来模拟Ethernet上的两台主机。
2)用一个双字类型变量Bus来模拟总线(将其初始化为“\0”,并且a总线等于“\0”,时表示总线空闲)。
3)两个子线程向总线发送自己的数据。数据用该线程的线程号进行模拟,发送数据用线程号和Bus的“或”操作进行模拟(即Bus=Bus||ID,,ID为该线程的线程号)。
4)每台主机须向总线上成功发送10次数据,如果其中某次数据发送失败,则该线程结束。
5)发送流程须遵循CSMA/CD。随机延迟算法中的冲突窗口取0.005。在数据发送成功(即Bus==ID)后,报告“ID send success”,产生冲突(Bus!=ID)后报告“ID send conllision”,发送失败(即冲突计数器值为0)后报告“ID send failure”。随着主机发送成功次数增加,报告其已发送成功的次数,如“主机A发送成功数=3。
3 相关知识
Ethernet的核心技术是随机争用型介质访问方法,即带有冲突检测的载波侦听多路访问(CSMA/CD)方法。
1.Ethernet的帧的发送流程
1)载波侦听过程。Ethernet中每个结点利用总线发送数据,总线是每个结点共享的公共传输介质。所以结点在发送一个帧前,必须侦听总线是否空闲。由于Ethernet的数据采用曼彻斯特编码方式,所以可以通过判断总线电平是否跳变来确定总线是否空
闲.若总线空闲,就可启动发送,否则继续侦听。
2)冲突检测。在数据发送过程中,可能会产生冲突(冲突是指总线上同时出现两个或两个以上的发送信号,它们叠加后的信号波形与任何发送结点输出的信号波形不相同。因为可能有多个主机都在侦听总线,当它们侦听到总线空闲时,都会往总线上发送数据)。所以在发送数据的过程中,也应该进行冲突检测,只要发现冲突就应该停止发送数据。
3)随机延迟后重发。在检测到冲突,停止发送后,结点进行随机延迟后重发。若重发16次后还没成功,则宣告发送失败,取消该帧的发送。随机延迟的计算方法一般采用截止二进制指数后退算法。该算法可表示为:?:τ=2k*R*a。其中τ为结点重新发送需要的后退延迟时间,a为冲突窗口值(冲突窗口为总线最大长度和电磁波在介质中的传播速度比值的2倍),R为随机数,k的取值为k=min(n,10),n为该帧已被发送的次数。图4-1给出了Ethernet帧发送流程。
2 Ethernet帧接收流程
帧接收流程大致可以分为以下三个步骤·
1)检查是否发生冲突,若发生冲突,则丢弃该帧;若没有冲突,进入下一步。
2)检查该帧的目的地址看是否可以接收该帧.若可以接收,则进入下一步。
3)检查CRC校验和LLC数据长度。若都正确,接收该帧,否则丢弃。
4 课程设计分析
1.设计中的重点及难点
1)模拟冲突的过程,在这个程序中不要使用任何线程同步机制。
1)若程序中不能模拟出冲突,可以在某些地方加入延时。
2.核心代码
int i=0;//发送成功砍数
int CollisionCounter=16;//冲突计数2S初始值为16
double collisionwindow=O.005;//冲突窗口值取O.05
int randNum=rand()%3;//随机数
Loop:if(Bus==0) //总线空闲
{
Bus=Bus|ID1; //模拟发送包
Sleep(12);
if(Bus==ID1) //无冲突
{
printf("%dSend success\n\n",IDl);//发送成功
Bus=0;//内存清零
CollisionCounter=16;//复原冲突计数器
Sleep(rand()%10);//随机延时
i++;
printf("主机a发送成功次数:%d\n\n",i);
if(i<10)
goto Loop;//发送次数不够lO次,开始下—次发送
}
else
{
printf(“%d Send Collision\n\n”,IDl);//发生冲突
Bus=O;
CollisionCounter-- //冲突计数器减1
if(CollisionCounter>0)
{//随机延迟重发.延迟算法用截止二进制指数后退算法sleep(randNum*(int) pow(2,(COlllsionCount>10)?10:CollisionCounter)
*collisionWindow);
goto Loop;//下一次尝试发送
}
else
printf(“%d Send faillure\n\n”,IDl);//重发次数超过16次,宣布发送失败
}
}
else //总线忙
goto Loop;//继续载波侦听
return 0;
3.程序流程
主程序流程框图
主程序中的程序流程框图为下图4-3,其中线程A和线程B的线程相同。
计算机网络课程设计题目三
----监控IP包流量
1 课程设计目的
随着Internet技术的发展,基于lP协议的网络应用成为网络技术研究与软件开发的一个重要基础,因此学习网络层的基本概念,了解IP协议的基本内容,对于掌握TCP/IP 协议的主要内容和学习网络课程是十分重要的。通过本实课程设计,有助于熟悉IP包格式和加深对IP协议的理解。
2课程设计要求
编制程序,监控网络,捕获…段时间内网络上的IP数据包,按IP数据包的源地址统计出该源地址在该时间段内发出的IP包的个数,将其写入日志文件中或用图形表示出来(建议用图形表示出统计结果)。
程序的具体要求如下:
用命令行运行:IPStatistic time logfile
其中,IPStatistic是程序名;time是设定的统计时间间隔(单位为分钟,比如,2表示2分钟);logfile表示统计结果写入的日志文件名(若用图形表示统计结果则可以不选这个参数)。
3 相关知识
IP是TCP/IP协议体系中的网络层协议。TCP、UDP、1CMP和IGMP等其他协议都是
以IP协议为基础的。IP协议的特点如下:
1)IP协议是一种不可靠、无连接的数据报传送协议。
2)IP协议是点对点的网络层通信协议。
3)IP协议向传输层隐藏了物理网络的差异。
IP数据包的格式可以参阅第7章。
4课程设计分析
1.课程设计中的重点及难点
1)程序中会用到Winpcap
计算机网络课程设计题目四UDP服务器设计