第二次寒假作业

这个作业属于哪个课程 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上

但是我将自己的学习过程一一记录了在这篇博客里

我只能将我能力范围内的构思呈现出来

看起来好像没什么内容,却花了好多心思,只能说尽力了哈哈哈哈

posted @ 2022-01-30 20:11  -减减-  阅读(47)  评论(1编辑  收藏  举报