优秀课设IP数据包解析.docx
- 文档编号:13361076
- 上传时间:2023-06-13
- 格式:DOCX
- 页数:16
- 大小:66.54KB
优秀课设IP数据包解析.docx
《优秀课设IP数据包解析.docx》由会员分享,可在线阅读,更多相关《优秀课设IP数据包解析.docx(16页珍藏版)》请在冰点文库上搜索。
优秀课设IP数据包解析
课程设计——解析IP数据包
长沙理工大学
目录
1、课程设计目的2
2、课程设计要求2
3、程序设计分析2
3.1网卡设置2
3.2.1使用套接字3
3.2.2接收数据包3
3.3定义IP头部的数据结构4
3.4IP包的解析4
3.5协议的定义5
3.6捕获处理5
4、运行结果6
5、总结6
6、课程设计参考资料7
7、源程序代码7
1、课程设计目的
本章课程设计的目的就是设计一个解析IP数据包的程序,并根据这个程序,明确课程设计的目的和重要性,认真领会课程设计的题目,读懂课程设计指导书的要求,学会设计的基本方法与步骤,学会如何运用前修知识与收集、归纳相关资料解决具体问题的方法。
严格要求自己,要独立思考,按时、独立完成能力拓展训练任务。
设计报告:
要求层次清楚,整洁,规范,不得相互抄袭。
2、课程设计要求
1、用两个线程a和b来模拟Ethernet上的两台主机。
2、用一个双字类型变量Bus来模拟总线(将其初始化为“\0”,并且总线等于“\0”时表示总线空闲)。
3、两个子线程向总线发送自己的数据。
数据用该线程的线程号进行模拟,发送数据用线程号和Bus的“或”操作进行模拟(即Bus=Bus|ID,ID为该线程的线程号)。
4、每台主机需向总线上成功发送10次数据,如果其中某次数据发送失败,则该线程结束。
5、发送流程必须遵循CSMA/CD。
随即延迟算法中的冲突窗口取0.005。
在数据发送成功3、程序设计分析
3.1网卡设置
为了获取网络中的IP数据包,必须对网卡进行编程,在这里使用套接字(socket)进行编程。
但是,在通常情况下,网络通信的套接字程序只能响应与自己硬件地址相匹配的数据包或是以广播形式发出的数据包。
对于其他形式的数据包,如已到达网络接口,但却不是发送到此地址的数据包,网络接口在骓投递地址并非自身地址之后将不引起响应,也就是说应用程序无法收取与自己无关的数据包。
我们要想获取网络设备的所有数据包,就是需要将网卡设置为混杂模式。
3.2.1使用套接字
套接字分为三种,即流套接字(Streamsocket)、数据报套接字(DatagramSocket)
和原始套接字(RawSocket)。
要进行IP层数据包的接收和发送,应使用原始套接字。
创建原始套接字的代码如下:
Socketsock:
Sock=WSASocket(AF_INET,SOCK_RAW,IPPROTO_TP,NULL,0,WSA_FLAG_OVERLAPPED);
本设计不用考虑超时情况。
创建套接后,IP头就会包含在接收数据包中。
然后,我可以设置IP头操作选项,调用setsockopt函数。
其中flag设置为true,并设定IP-HDRINCL选项,表明用户可以亲自对IP头进行处理。
最后使用bind()函数将socket绑定到本地网卡上。
绑定网卡后,需用WSAIoctl()函数把网卡设置为混杂模式,使网卡能够接收所有的网络数据。
如果接收的数据包中的协议类型和定义的原始套接字匹配,那么接收的数据就拷贝到套接字中,因此,网卡就可以接收所有经过的IP包。
3.2.2接收数据包
在程序中可使用recv()函数接收经过的IP包。
该函数有四个参数,第一个参数接收操作所用的套接字描述符;第二个参数接收缓冲区的地址;第三个参数接收缓冲区的大小,也就是所要接收的字节数;第四个参数是一个附加标志,如果对所发送的数据没特殊要求,直接设为0。
因为IP数据包的最大长度是65535B,因此缓冲区的大小不能小于65535B。
设置缓冲区后,可利用循环来反复监听接收IP包,用recv()函数实现接收功能。
3.3定义IP头部的数据结构
程序需要定义一个数据结构表示IP头部。
其代码如下:
inti=0;//发送成功次数
intCollisionCounter=16;//冲突计数器初始值为16
doubleCollisionWindow=0.005;//冲突窗口值取值0.005
intrandNum=rand()%3;//随机数
loop:
if(Bus==0)//总线空闲
{
Bus=Bus|ID1;//模拟发送包
Sleep(12);
if(Bus==ID1)//无冲突
{
printf("%dSendSuccess\n\n",ID1);//发送成功
Bus=0;//内存清零
CollisionCounter=16;//复原冲突计数器
Sleep(rand()%10);//随即延时
i++;
printf("主机a发送成功次数=%d\n\n",i);
if(i<10)
gotoloop;//发送次数不够10次,开始下一次发送
}
else
{
printf("%dSendCollision\n\n",ID1);//发生冲突
CollisionCounter--;
Bus=0;3.4IP包的解析
解析IP包的字段有两种策略。
针对长度为8位、16位和32位的字段(或子字段)时,可以利用IP-HEADER的成员直接获取。
要解析长度不是8位倍数的字段(或子字段)时,可以利用C语言中的移位以人、及与、或操作完成。
3.5协议的定义
(包含相应的头文件#include#include):
DWORDdwIoControlCode=SIO_RCVALL,/*接收所有的IP包*/
dwProtocol=IPPROTO_IP;/*协议类型为IP*/
3.6捕获处理
1.加载Winsock;
2.创建一个接收原始IP包的socket连接;
3.绑定到一个接口;
4.进行WSAIoctl设置,接收所有的IP数据包。
代码如下:
if(WSAIoctl(s,dwIoControlCode,&optval,sizeof(optval),
NULL,0,&dwBytesRet,NULL,NULL)==SOCKET_ERROR)
5.接着设定一个线程进行捕获:
(1)创建一个接收IP包的链表头;
(2)设置一个标识,为真,则不断进行IP包的捕获;
(3)建立一个新的结点,将捕获的数据包加入到该结点;
(4)如果链表的长度达到指定的长度,创建一个线程对该链表的IP包进行解析;再设置一个在IP数据包链表不足给定的长度,而又中止IP捕获时,对链表的处理;
(5)为下一个IP包链表创建一个链表头。
6.建立一个进行IP包解析并显示的线程,进行解析IP数据包,然后显示IP数据包。
4、运行结果
截获IP数据包程序运行结果如下:
5、总结
这次计算机网络课程设计是解析IP数据包,通过这次上机充分应用了所学的计算机网络和C语言的知识,并上网搜索一部分相当资料,粗略设计出该程序。
通过本次课程设计,首先认识到了自己的不足。
在编码的过程中认识到了自己细节方面的不足,在以后计算机网络的学习过程中在理解的同时还要做到对细节的注重;当然在本次课设中最终还是实现了题目要求。
同时,觉得本次课设是十分有意义的,使自己所学的只是有了实践的地方。
6、课程设计参考资料
《计算机网络(第四版)》 主编:
谢希仁出版社:
电子工业出版社出版时间:
2004年7月
《计算机网络课程设计》主编:
吴功宜胡晓英张仁何云王宁出版社:
机械工业出版社
出版或修订时间:
2005年9月
《计算机网络设计》主编:
易建勋出版社:
人民邮电出版社出版或修订时间:
2007年10月
7、源程序代码
#include"winsock2.h"
#include"ws2tcpip.h"
#include"iostream"
#include"stdio.h"
#pragmacomment(lib,"ws2_32.lib")
typedefstruct_IP_HEADER//定义IP头
{
union
{
BYTEVersion;//版本(前4位)
BYTEHdrLen;//IHL(后4位),报头标长
};
BYTEServiceType;//服务类型
WORDTotalLen;//总长
WORDID;//标识
union
{
WORDFlags;//标志(前3位)
WORDFragOff;//分段偏移(后13位)
};
BYTETimeToLive;//生命期
BYTEProtocol;//协议
WORDHdrChksum;//头校验和
DWORDSrcAddr;//源地址
DWORDDstAddr;//目的地址
BYTEOptions;//选项
}IP_HEADER;
//逐位解析IP头中的信息
voidgetVersion(BYTEb,BYTE&version)
{
version=b>>4;//右移4位,获取版本字段
}
voidgetIHL(BYTEb,BYTE&result)
{
result=(b&0x0f)*4;//获取头部长度字段
}
char*parseServiceType_getProcedence(BYTEb)
{
switch(b>>5)//获取服务类型字段中优先级子域
{
case7:
return"NetworkControl";
break;
case6:
return"InternetworkControl";
break;
case5:
return"CRITIC/ECP";
break;
case4:
return"FlashOverride";
break;
case3:
return"Flsah";
break;
case2:
return"Immediate";
break;
case1:
return"Priority";
break;
case0:
return"Routine";
break;
default:
return"Unknow";
break;
}
}
char*parseServiceType_getTOS(BYTEb)
{
b=(b>>1)&0x0f;//获取服务类型字段中的TOS子域
switch(b)
{
case0:
return"Normalservice";
break;
case1:
return"Minimizemonetarycost";
break;
case2:
return"Maximizereliability";
break;
#include
#include
#include
#include
#include
#include
#include
#include
#include
#defineERROR_SHMGET-1
#defineERROR_SHMAT-2
#defineERROR_WAIT-3
#defineERROR_FORK-4
#defineSLOT_TIME0.005
/*截止二进制指数退避算法的实现
该算法可以表示为:
t=2*τ*r为结点重新发送需要的后退延迟时间;2*τ为冲突窗口值;
r为随机数,r的取值范围为[0,2^k-1],k=Min[重传次数,10];
当重传16次仍不成功时,则丢弃该帧.
*/
staticunsignedlongget_backoff(constintn)//计算重传推迟时间
{
intk=n;
k=16-k;
if(k>10)//如果重传次数大于10时,重传次数置为10
k=10;
return(random()%(1< } /*发送数据流程*/ staticvoidsend_msg(constvoid*addr,constpid_tpid,charch) { pid_t*bus=(pid_t*)addr; intcollision;//冲突计数器 intk=0;//发送成功的次数 for(inti=0;i<10;i++) { collision=16; do { while(*bus! =0);//总线不空闲,循环等待直到总线空闲. usleep(SLOT_TIME/2);//检测到总线为空闲时就开始发送数据,因为线程A和B共享总线 变量bus,所以在τ时间以内,另一个线程收不到数据,所以要进行此操作 *bus|=pid;//表示另一个进程受收到模拟数据. usleep(SLOT_TIME/2);//从模拟数据发送后经过2τ时间之后进行判断. //判断是否冲突,共享内存与写入内存比较,若相同则无冲突,否则发生冲突. if(*bus! =pid) { *bus=0;//复原总线为0 collision--; if(collision>0) { printf("%dsendcollision.\n",pid); usleep(get_backoff(collision));//随机延时 } else { printf("%dsendfailure.\n",pid);//发送失败 break; } } else { *bus=0; break; } }while (1); if(collision>0) { k++; printf("%dsendsuccess.\n",pid); printf("%csendsuccess=%d.\n",ch,k); } usleep(random()%1024); } }/*主 函 数 */ intmain() { pid_tpid=0; intbus=0;/*共享内存的ID,用来模拟总线*/ void*addr=0;/*指向模拟总线的首地址*/ bus=shmget(IPC_PRIVATE,sizeof(pid_t),SHM_R|SHM_W);//获取共享内存 if(bus==-1)/*如果申请内存失败*/ { perror("shmgeterror."); returnERROR_SHMGET; } if((pid=fork())<0)//创建子进程a { perror("forkerror."); returnERROR_FORK; } elseif(pid==0) { pid=getpid();//获取子进程ID addr=shmat(bus,0,0);//初始化共享内存为\0 if(addr==(void*)-1) { perror("shmaterror"); /*shmctl(shmid,IPC_RMID,0)是释放共享内存区, 这只有在所有进程中的shmid都已经无效化后才会进行, 如果shmid的引用计数没有变为0,就已经调用了shmctl(shmid,IPC_RMID,0) ,则该函数什么也不做,一直等到最后一个shmdt()调用时,就执行释放共享内存的任务。 */ if(shmctl(bus,IPC_RMID,0)==-1) { perror("shmctlerror"); } returnERROR_SHMAT; } /*srandom()方法的原型如下: functionvoidsrandom(intseed); srandom()方法使用指定的种子值初始化一个对象的随机数发生器,赋随机数种子值*/ srandom((unsignedint)time(NULL)); send_msg(addr,pid,'A');//发送数据 } elseif(pid>0) { if((pid=fork())<0)//创建子进程b { perror("forkerror"); returnERROR_FORK; } elseif(pid==0) { pid=getpid();//获取子进程ID addr=shmat(bus,0,0);//初始化共享内存为\0 if(addr==(void*)-1) { perror("shmaterror."); if(shmctl(bus,IPC_RMID,0)==-1) { perror("shmctlerror."); } returnERROR_SHMAT; } srandom((unsignedint)time(NULL)); send_msg(addr,pid,'B'); } elseif(pid>0) { if(wait(NULL)==-1) { perror("waiterror."); returnERROR_WAIT; } else { return0; } } } return0; }
- 配套讲稿:
如PPT文件的首页显示word图标,表示该PPT已包含配套word讲稿。双击word图标可打开word文档。
- 特殊限制:
部分文档作品中含有的国旗、国徽等图片,仅作为作品整体效果示例展示,禁止商用。设计者仅对作品中独创性部分享有著作权。
- 关 键 词:
- 优秀 IP 数据包 解析