第二次寒假作业
这个作业属于哪个课程 | 2020面向对象程序设计 |
---|---|
这个作业要求在哪里 | 第二次寒假作业 |
这个作业的目标 | 了解计算机网络相关知识、学习C语言读写文件、模块化实现函数...... |
作业正文 | 如下 |
前言
其实我没什么前言,但是看到大家都这样写,那我也写一个吧
就是好难甚至一开始都搞不懂在说啥好痛苦好绝望
之后就查阅各种资料,借鉴了他人的作业,看了好多网课,划了好多水hhh
程序没有实现,但是我的构思已经清楚的呈现在下面啦🧐🧐
本次作业需要学习的内容
1、学习计算机网络关于规则集、数据集、规则匹配的相关知识,充分了解什么是规则匹配,如何做到规则匹配等。
2、学习C++语言中对文件的读写。
3、思考实现规则匹配需要哪些步骤,并分模块规划,先创建各分块函数组,再一一实现。最好是先用伪代码和流程图等方式理清思路,做好分工。
4、根据各个函数的功能进行测试、优化,再将代码和测试过程整合至GitHub上。
5、期间也要不断巩固git知识,熟练掌握常见用法。
学习过程
1、理清规则集与数据集的概念
规则集 | 原IP地址 | 目的IP地址 | 源端口 | 目的端口 | 传输层协议 |
---|---|---|---|---|---|
(范围、点分十进制) | 178.139.217.251/32 | 126.0.44.183/32 | 0:65535 | 1526:1526 | 0x06/0xFF |
数据集 | 2995509645 | 269990131 | 0 | 0 | 255 |
(十进制) |
既然规则集和数据集的表示方法不同,那么首先要有一个函数来转化进制。
2、如何判断规则匹配
IP地址的匹配是我最最最难理解的东西
然后我就从别人作业找到了一个介绍IP地址范围的,看得更更更痛苦了
https://blog.csdn.net/dan15188387481/article/details/49873923
【这part垮了】
首先将规则集的点分十进制改写成二进制
eg:128.14.35.7/20 --> 10000000 00001110 00100011 00000111(其中前二十位是网络前缀)
接下来令主机号分别全为0和1得到规则集地址范围
eg:最小地址:10000000 00001110 00100000 00000000 --> 128.14.32.0
最大地址:10000000 00001110 00101111 11111111 --> 128.14.47.255
【后来在咨询了身为计算机研究生的姐姐之后,我发现IP范围啥的都不重要...】
然后将数据集中的IP地址转化为点分十进制(或点分十进制转化为整数形式)
点分十进制就是用四个0~255的数字来表示一个IP地址(二进制均为八位)
这里我选择将点分十进制统一改写成整数形式的IP地址
actually我看不懂这玩意,打算之后再慢慢学吧
maybe我就摆烂开抄
最后就是比对原/目的IP地址、原/目的端口范围是否符合
这里我打算用两次循环,一次用来按行读取数据包数据,内嵌套一次用来与规则集内的数据比对匹配
3、学习C语言对文件的读写
读取文件
先学习打开文件、读取文件等等基本函数指令
之后还要了解清楚读取的方式,如何将文件内的数据读取进数组里
最后设置条件(换行符)按行读取
这里我借此机会系统的学习了C语言的文件操作
要读取文件当然打开是第一步
接下来是按行读取
在这我只知道fgets的用法、读取结束的标志
但是我还是不知道如何去按行读取
之后我又去搜索了fgets()函数的使用
原来fgets遇到换行符,第二次就会从下一行开始读入数据!!
这时行数据就存储在了一维数组s内
书写文件
类似于读取文件,这里用到了fputs()函数
首先设置一个文件指针 FILE*p
使指针指向要写入的文件p=fopen("res.txt”,"a")
这里用“a"书写以便补位添加,首先要创建一个"res"文本文件,否则将书写失败
后用fputs(ch,p)将答案写入文件(附带换行符)
最后fclose(p)关闭文件
按功能分块设置代码函数
1、读取、关闭文件
void read()
{
char file;//文件名
FILE *fp;//定义文件指针
printf("Enter the name of the file to be processed:");//输入要打开的文件名称
scanf("%s",file);
fp=fopen(file,"r"); //打开文件,r表示只读,w只写......
if (fp==NULL)
{
printf("不存在文件%s\n",file);
} //不存在此文件
char prime[500];
while((fgets(prime,500,fp))!=NULL)//按行读取文件的循环
{
char IP1[100],IP2[100],former[100],goal[100],duc[100];
int a,b,c,d,e;
for(a=0;prime[a]!=' ';a++) //a表示该IP地址的位数-1
{
IP1[a]=prime[a];
} //用空格标志已读完原IP地址
int A=a;
a-=1;
for(;prime[A]==' ';A++)//找到下一个目的IP地址开始的标志
for(b=0;prime[A]!=' ';A++,b++)
//b表示该IP地址的位数-1,而A使prime数组可继续读取
{
IP2[b]=prime[A];
}
b-=1;
for(;prime[A]==' ';A++)//找到下一个源端口开始的标志
for(c=0;prime[A]!=' ';A++,c++) //同理c表示该源端口的位数-1
{
former[c]=prime[A];
}
c-=1;
//将源端口数组转化为整数Former
int C,Former;
for(C=0,Former=0;c>=0;c--,C++)
{
Former+=former[C]*pow(10,c);
}
for(;prime[A]==' ';A++)//找到下一个目的端口开始的标志
for(d=0;prime[A]!=' ';A++,d++) //d表示该目的端口的位数
{
goal[d]=prime[A];
}
d-=1;
//将目的端口数组转化为整数Goal
int D,Goal;
for(D=0,Goal=0;d>=0;d--,D++)
{
Goal+=former[D]*pow(10,d);
}
for(;prime[A]==' ';A++)//找到下一个协议号开始的标志
for(e=0;prime[A]!='\n';A++,e++) //e表示该协议号的位数
{
duc[e]=prime[A];
}
}
}
这样就非常白痴的读完了一行的数据,并分别放在了五个数组里区分
(我也不知道这样的做法是否正确,这是基于我只学过这么多知识才做的hhh)
对应的在完成所有操作的时候关闭文件
fclose(fp);
2、转化进制
这个我不会👻👻
3、比对
void compare()
{
//假设这是在打开规则集文件的循环里
FILE *fp2;//定义文件指针
fp2=fopen("rule1","r");//打开规则集文件
int cnt=0;//计算行数
while((fgets(rule,500,fp2))!=NULL)
{
//那么这里我们假设已经转化完相同的整数形式进数组里了嘻嘻
//规则集里转换完的数据分别是t1[]、t2[]、t3[]、t4[]、t5[]
int i,f=0;
for(i=0;IP1[i]!='\n';i++)//比对源IP地址
{
if(IP1[i]!=t1[i])
{
f=1;
break;
}
}
if(f)
{
cnt++;//发现不匹配,行数增加
continue;//进下一行
}
for(i=0;IP2[i]!='\n';i++)//比对源IP地址
{
if(IP2[i]!=t2[i])
{
f=1;
break;
}
}
if(f)
{
cnt++;//发现不匹配,行数增加
continue;//进下一行
}
//接下来是从数组表示的范围中提取
int j,formermin=0,formermax=0;
for(j=0;t3[j]!=' ';j++)//找到最值的分界
int k=j;//最小值的位数
for(;k>0;k--)
{
formermin+=t3[j-k]*pow(10,k);
} //得出最小值
k=j+4; //最大值的数组起点
j+=4;
for(;t3[k]>=0&&t3[k]<=9;k++)//找到最大值的边界
for(;j<k;j++)
{
formermax+=t3[j]*pow(10,k-j-1);
} //得出最大值
//对转化成整数的端口进行比对
if(Former>=formermin&&Former<=formermax)
f=0;
else
f=1;
if(f)
{
cnt++; //发现不匹配,行数增加
continue; //进下一行
}
//同理转化目的端口范围进行比对
int goalmin=0,goalmax=0;
for(j=0;t4[j]!=' ';j++)//找到最值的分界
k=j; //最小值的位数
for(;k>0;k--)
{
goalmin+=t4[j-k]*pow(10,k);
} //得出最小值
k=j+4; //最大值的数组起点
j+=4;
for(;t4[k]>=0&&t4[k]<=9;k++)//找到最大值的边界
for(;j<k;j++)
{
goalmax+=t4[j]*pow(10,k-j-1);
} //得出最大值
//对转化成整数的端口进行比对
if(Goal>=goalmin&&Goal<=goalmax)
f=0;
else
f=1;
if(f)
{
cnt++; //发现不匹配,行数增加
continue; //进下一行
}
//最后比对协议号
//题目给出的情况其实只有两种:一是协议号为6,全部匹配;二是协议号非6,则只与0x00匹配
//那么我们只需要看数据包协议号是否为6,再看规则集协议号的最后一个字符是F还是0
if(duc[e-1]==6&&e==1) //如果是6,则全匹配
f=0;
else if(t5[8]==0) //若非6,但规则集0x00,也匹配
f=0;
else //其他情况不匹配
f=1;
if(f)
{
cnt++;//发现不匹配,行数增加
continue;//进下一行
}
if(f==0)
{
//这里链接到下一个输出文件的函数,最终输出行数
}
}
}
4、输出文件
void write()
{
FILE *p;
p=fopen("res.txt","a");//要先创建文件才能输出喔
char ans[2];//构建有答案行数和换行符的数组
ans[0]=cnt;
ans[1]='\n';
fputs(ans,p);
fclose(p);
}
总结
这次的作业我只能勉强搞懂要求是什么
在了解了很多计算机网络的知识和询问了他人后,才真正明白要解决什么问题
但是仍然无法自主学习完整,只能完成这么小部分的任务
我的代码都比较零散,所以就呈现在这了,没有办法整合到GitHub上
但是我将自己的学习过程一一记录了在这篇博客里
我只能将我能力范围内的构思呈现出来
看起来好像没什么内容,却花了好多心思,只能说尽力了哈哈哈哈