CCFCSP刷题之路---202104-3 DHCP服务器(C/C++ 100分)

简介: CCFCSP刷题之路---202104-3 DHCP服务器(C/C++ 100分)

一、题目描述
报文格式
为了便于实现,我们简化地规定 DHCP 数据报文的格式如下:

<发送主机> <接收主机> <报文类型> <过期时刻>

DHCP 数据报文的各个部分由空格分隔,其各个部分的定义如下:

发送主机:是发送报文的主机名,主机名是由小写字母、数字组成的字符串,唯一地表示了一个主机;
接收主机:当有特定的接收主机时,是接收报文的主机名;当没有特定的接收主机时,为一个星号(*);
报文类型:是三个大写字母,取值如下:
DIS:表示 Discover 报文;
OFR:表示 Offer 报文;
REQ:表示 Request 报文;
ACK:表示 Ack 报文;
NAK:表示 Nak 报文;
IP 地址,是一个非负整数:
对于 Discover 报文,该部分在发送的时候为 0,在接收的时候忽略;
对于其它报文,为正整数,表示一个 IP 地址;
过期时刻,是一个非负整数:
对于 Offer、Ack 报文,是一个正整数,表示服务器授予客户端的 IP 地址的过期时刻;
对于 Discover、Request 报文,若为正整数,表示客户端期望服务器授予的过期时刻;
对于其它报文,该部分在发送的时候为 0,在接收的时候忽略。
例如下列都是合法的 DHCP 数据报文:

a * DIS 0 0
d a ACK 50 1000

服务器配置
为了 DHCP 服务器能够正确分配 IP 地址,DHCP 需要接受如下配置:

地址池大小 :表示能够分配给客户端的 IP 地址的数目,且能分配的 IP 地址是 ;
默认过期时间 :表示分配给客户端的 IP 地址的默认的过期时间长度;
过期时间的上限和下限 、:表示分配给客户端的 IP 地址的最长过期时间长度和最短过期时间长度,客户端不能请求比这个更长或更短的过期时间;
本机名称 :表示运行 DHCP 服务器的主机名。
分配策略
当客户端请求 IP 地址时,首先检查此前是否给该客户端分配过 IP 地址,且该 IP 地址在此后没有被分配给其它客户端。如果是这样的情况,则直接将 IP 地址分配给它,否则,
总是分配给它最小的尚未占用过的那个 IP 地址。如果这样的地址不存在,则分配给它最小的此时未被占用的那个 IP 地址。如果这样的地址也不存在,说明地址池已经分配完毕,因此拒绝分配地址。

实现细节
在 DHCP 启动时,首先初始化 IP 地址池,将所有地址设置状态为未分配,占用者为空,并清零过期时刻。
其中地址的状态有未分配、待分配、占用、过期四种。
处于未分配状态的 IP 地址没有占用者,而其余三种状态的 IP 地址均有一名占用者。
处于待分配和占用状态的 IP 地址拥有一个大于零的过期时刻。在到达该过期时刻时,若该地址的状态是待分配,则该地址的状态会自动变为未分配,且占用者清空,过期时刻清零;否则该地址的状态会由占用自动变为过期,且过期时刻清零。处于未分配和过期状态的 IP 地址过期时刻为零,即没有过期时刻。

对于收到的报文,设其收到的时刻为 。处理细节如下:

判断接收主机是否为本机,或者为 *,若不是,则判断类型是否为 Request,若不是,则不处理;
若类型不是 Discover、Request 之一,则不处理;
若接收主机为 *,但类型不是 Discover,或接收主机是本机,但类型是 Discover,则不处理。
对于 Discover 报文,按照下述方法处理:

检查是否有占用者为发送主机的 IP 地址:
若有,则选取该 IP 地址;
若没有,则选取最小的状态为未分配的 IP 地址;
若没有,则选取最小的状态为过期的 IP 地址;
若没有,则不处理该报文,处理结束;
将该 IP 地址状态设置为待分配,占用者设置为发送主机;
若报文中过期时刻为 0 ,则设置过期时刻为 ;否则根据报文中的过期时刻和收到报文的时刻计算过期时间,判断是否超过上下限:若没有超过,则设置过期时刻为报文中的过期时刻;否则则根据超限情况设置为允许的最早或最晚的过期时刻;
向发送主机发送 Offer 报文,其中,IP 地址为选定的 IP 地址,过期时刻为所设定的过期时刻。
对于 Request 报文,按照下述方法处理:

检查接收主机是否为本机:
若不是,则找到占用者为发送主机的所有 IP 地址,对于其中状态为待分配的,将其状态设置为未分配,并清空其占用者,清零其过期时刻,处理结束;
检查报文中的 IP 地址是否在地址池内,且其占用者为发送主机,若不是,则向发送主机发送 Nak 报文,处理结束;
无论该 IP 地址的状态为何,将该 IP 地址的状态设置为占用;
与 Discover 报文相同的方法,设置 IP 地址的过期时刻;
向发送主机发送 Ack 报文。
二、代码实现

#include<bits/stdc++.h>
using namespace std;
typedef long long ll;

struct IP
{
    ll state;//0---未分配,1---待分配,2---占用,3---过期
    string occ_host;
    ll ip_out;
}ip[10005];

//N:地址池大小
//t_def:默认过期时间
//t_max、t_min:过期时间的上下限
//H:本机名称
ll N,n,t_def,t_max,t_min;
string H;
ll rec_time,ip_ads,time_out;
string send_host,rec_host,type;

ll search_ip()
{
    for(ll i=1;i<=N;i++)
    {
        if(ip[i].occ_host==send_host) return i;
    }
    for(ll i=1;i<=N;i++)
    {
        if(ip[i].state==0) return i;
    }
    for(ll i=1;i<=N;i++)
    {
        if(ip[i].state==3) return i;
    }
    return -1;
}

void check()
{
    for(ll i=1;i<=N;i++)
    {
        if(ip[i].ip_out<=rec_time)
        {
            if(ip[i].state==1)
            {
                ip[i].state = 0;
                ip[i].occ_host = "";
            }
            if(ip[i].state==2)
            {
                ip[i].state = 3;
            }
        }
    }
}

int solve()
{
        check();
        if(rec_host!=H && rec_host!="*")
        {
            if(type!="REQ") return 0;
        }
        if(type!="DIS" && type!="REQ") return 0;
        if(rec_host=="*" && type!="DIS") return 0;
        if(rec_host==H && type=="DIS") return 0;

        if(type=="DIS")
        {
            ll x_ip = search_ip();
            if(x_ip==-1) return 0;

            ip[x_ip].state = 1;
            ip[x_ip].occ_host = send_host;

            if(time_out==0) ip[x_ip].ip_out = rec_time + t_def;
            else
            {
                ll x_ot = time_out;
                x_ot = max(rec_time+t_min,x_ot);
                x_ot = min(rec_time+t_max,x_ot);
                ip[x_ip].ip_out = x_ot;
            }

            cout<<H<<" "<<send_host<<" OFR "<<x_ip<<" "<<ip[x_ip].ip_out<<endl;
        }
        else if(type=="REQ")
        {
            if(rec_host!=H)
            {
                for(ll i=1;i<=N;i++)
                {
                    if(ip[i].occ_host==send_host && ip[i].state==1)
                    {
                        ip[i].state = 0;
                        ip[i].occ_host = "";
                        ip[i].ip_out = 0;
                    }
                }
                return 0;
            }

            if(ip_ads > N || ip[ip_ads].occ_host!=send_host)
            {
                cout<<H<<" "<<send_host<<" NAK "<<ip_ads<<" 0"<<endl;
                return 0;
            }

            if(time_out==0) ip[ip_ads].ip_out = rec_time + t_def;
            else
            {
                ll x_ot = time_out;
                x_ot = max(rec_time+t_min,x_ot);
                x_ot = min(rec_time+t_max,x_ot);
                ip[ip_ads].ip_out = x_ot;
            }

            ip[ip_ads].state = 2;
            cout<<H<<" "<<send_host<<" ACK "<<ip_ads<<" "<<ip[ip_ads].ip_out<<endl;
        }
        return 0;
}

int main()
{
    cin>>N>>t_def>>t_max>>t_min>>H;
    cin>>n;

    for(int i=1;i<=N;i++)
    {
        ip[i].state = 0;
        ip[i].occ_host = "";
    }

    for(int i=0;i<n;i++)
    {
        cin>>rec_time>>send_host>>rec_host>>type>>ip_ads>>time_out;
        solve();
    }
    return 0;
}
相关实践学习
深入解析Docker容器化技术
Docker是一个开源的应用容器引擎,让开发者可以打包他们的应用以及依赖包到一个可移植的容器中,然后发布到任何流行的Linux机器上,也可以实现虚拟化,容器是完全使用沙箱机制,相互之间不会有任何接口。Docker是世界领先的软件容器平台。开发人员利用Docker可以消除协作编码时“在我的机器上可正常工作”的问题。运维人员利用Docker可以在隔离容器中并行运行和管理应用,获得更好的计算密度。企业利用Docker可以构建敏捷的软件交付管道,以更快的速度、更高的安全性和可靠的信誉为Linux和Windows Server应用发布新功能。 在本套课程中,我们将全面的讲解Docker技术栈,从环境安装到容器、镜像操作以及生产环境如何部署开发的微服务应用。本课程由黑马程序员提供。 &nbsp; &nbsp; 相关的阿里云产品:容器服务 ACK 容器服务 Kubernetes 版(简称 ACK)提供高性能可伸缩的容器应用管理能力,支持企业级容器化应用的全生命周期管理。整合阿里云虚拟化、存储、网络和安全能力,打造云端最佳容器化应用运行环境。 了解产品详情: https://www.aliyun.com/product/kubernetes
相关文章
|
6月前
|
应用服务中间件 网络安全 数据安全/隐私保护
网关服务器配置指南:实现自动DHCP地址分配、HTTP服务和SSH无密码登录。
哇哈哈,道具都准备好了,咱们的魔术秀就要开始了。现在,你的网关服务器已经魔法满满,自动分配IP,提供网页服务,SSH登录如入无人之境。而整个世界,只会知道效果,不会知道是你在幕后操控一切。这就是真正的数字世界魔法师,随手拈来,手到擒来。
330 14
|
7月前
|
网络协议 安全
DHCP服务器配置
DHCP(动态主机配置协议)是一种用于自动分配IP地址及相关网络参数的协议,旨在简化网络管理、减少手动配置的工作量并避免IP地址冲突。其工作过程包括发现、提供、请求和确认四个阶段,确保设备快速安全接入网络。关键概念包括IP地址池、租约、作用域和静态分配等。DHCP通过自动化、动态性和冲突避免等功能,支持网络设备高效接入与管理。
472 21
|
网络协议 Windows
Windows Server 2019 DHCP服务器搭建
Windows Server 2019 DHCP服务器搭建
322 3
|
网络协议 Windows
Windows Server 2003 DHCP服务器搭建
Windows Server 2003 DHCP服务器搭建
138 2
|
存储 监控 NoSQL
Redis的实现二: c、c++的网络通信编程技术,让服务器处理多个client
本文讨论了在C/C++中实现服务器处理多个客户端的技术,重点介绍了事件循环和非阻塞IO的概念,以及如何在Linux上使用epoll来高效地监控和管理多个文件描述符。
178 1
|
Linux C语言 C++
vsCode远程执行c和c++代码并操控linux服务器完整教程
这篇文章提供了一个完整的教程,介绍如何在Visual Studio Code中配置和使用插件来远程执行C和C++代码,并操控Linux服务器,包括安装VSCode、安装插件、配置插件、配置编译工具、升级glibc和编写代码进行调试的步骤。
2606 0
vsCode远程执行c和c++代码并操控linux服务器完整教程
|
10月前
|
编译器 C++ 开发者
【C++篇】深度解析类与对象(下)
在上一篇博客中,我们学习了C++的基础类与对象概念,包括类的定义、对象的使用和构造函数的作用。在这一篇,我们将深入探讨C++类的一些重要特性,如构造函数的高级用法、类型转换、static成员、友元、内部类、匿名对象,以及对象拷贝优化等。这些内容可以帮助你更好地理解和应用面向对象编程的核心理念,提升代码的健壮性、灵活性和可维护性。
|
6月前
|
人工智能 机器人 编译器
c++模板初阶----函数模板与类模板
class 类模板名private://类内成员声明class Apublic:A(T val):a(val){}private:T a;return 0;运行结果:注意:类模板中的成员函数若是放在类外定义时,需要加模板参数列表。return 0;
166 0
|
6月前
|
存储 编译器 程序员
c++的类(附含explicit关键字,友元,内部类)
本文介绍了C++中类的核心概念与用法,涵盖封装、继承、多态三大特性。重点讲解了类的定义(`class`与`struct`)、访问限定符(`private`、`public`、`protected`)、类的作用域及成员函数的声明与定义分离。同时深入探讨了类的大小计算、`this`指针、默认成员函数(构造函数、析构函数、拷贝构造、赋值重载)以及运算符重载等内容。 文章还详细分析了`explicit`关键字的作用、静态成员(变量与函数)、友元(友元函数与友元类)的概念及其使用场景,并简要介绍了内部类的特性。
260 0
|
8月前
|
编译器 C++ 容器
【c++11】c++11新特性(上)(列表初始化、右值引用和移动语义、类的新默认成员函数、lambda表达式)
C++11为C++带来了革命性变化,引入了列表初始化、右值引用、移动语义、类的新默认成员函数和lambda表达式等特性。列表初始化统一了对象初始化方式,initializer_list简化了容器多元素初始化;右值引用和移动语义优化了资源管理,减少拷贝开销;类新增移动构造和移动赋值函数提升性能;lambda表达式提供匿名函数对象,增强代码简洁性和灵活性。这些特性共同推动了现代C++编程的发展,提升了开发效率与程序性能。
302 12

热门文章

最新文章