CSP202104-3 DHCP服务器

题目链接

问题分析:

这道题是一个相对简单的大模拟,只要抓住题中的细节信息就可以很容易的做出。
首先明确题目要求的DHCP报文格式

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

其次关注题目中所定义的分配策略。我们可以直接看其实现细节即可,其余信息对我们没有帮助。通过阅读题目,显然我们需要维护一个地址池来进行操作,由于数据量并没有很大,所以在操作时直接遍历爆搜即可。
首先定义地址池

struct IPinf
{
	ll state;//代表状态
	ll T;//代表时限
	string user;//代表该IP的占用者
};

操作可以分为下面五种

  • 对服务器初始化
    在 DHCP 启动时,首先初始化 IP 地址池,将所有地址设置状态为未分配,占用者为空,并清零过期时刻。
void ini()
{
	for(int i=1;i<=N;i++)
	{
		IPs[i].state = 0;
		IPs[i].T = 0;
		IPs[i].user = "";
	}
}
  • 对收到的不合规报文不进行处理
if(!(server==H||(server=="*")))
{
	if(type != "REQ")
			continue;
}
if(!(type=="REQ"||type=="DIS"))
	continue;
if(((server == "*"&&type!="DIS") || (server==H&&type=="DIS")))
	continue;
  • 对IP地址池进行更新
    在合法的操作之前进行更新即可,将超出时限的IP根据题目规则进行状态变换。
void update(ll ti)
{
	for(int i=1;i<=N;i++)
	{
		if(IPs[i].T!=0 && IPs[i].T <= ti)
		{
			if(IPs[i].state == 1)
			{
				IPs[i].state = 0;
				IPs[i].T = 0;
				IPs[i].user = "";
			}
			else if(IPs[i].state == 2)
			{
				IPs[i].state = 3;
				IPs[i].T = 0;
			}
		}
	}
}
  • 处理Discover报文

void DIS(ll ti, ll Tdef, ll T, string client)
{
	ll IP_to_client=0; //先定义将要分配的IP
	int flag = 0;//定义flag,判断是否能够正确分配IP
	for(int i=1;i<=N;i++)
	{
		if(IPs[i].user == client) //题目要求的条件1
		{						//如果有使用者为当前user的IP,则直接分配
			IP_to_client = i;
			flag = 1;
			break;
		}
	}
	for(int i=1;i<=N &&flag == 0;i++)//题目要求的条件二
	{							//如果存在未被分配的IP,则用最小的分配
		if(IPs[i].state==0)
		{
			IP_to_client = i;
			flag = 2;
			break;
		}
	}
	for(int i=1;i<=N&&flag==0;i++)//题目要求条件三
	{							//如果不存在未被分配的IP,则用最小的超时的IP分配
		if(IPs[i].state==3)
		{
			IP_to_client = i;
			flag = 3;
			break;
		}
	}
	if(flag == 0)//如果都没能分配,则直接返回不作处理
		return;
	ll tempt;
	if(T==0)//如果没有指定时限,则自动分配
		tempt = ti+Tdef;
	else//如果指定时限,那么判断是否合规,然后分配
	{
		tempt = T-ti;
		tempt = min(tempt, Tmax);
		tempt = max(tempt, Tmin);
		tempt = tempt+ti;
	}
	//存入状态
	IPs[IP_to_client].state = 1;
	IPs[IP_to_client].user = client;
	IPs[IP_to_client].T = tempt;
	//按要求输出即可
	cout<<H<<" "<<client<<" "<<"OFR"<< " "<<IP_to_client<<" "<<tempt<<endl;
}
  • 处理Request报文
void REQ(ll ti, ll T, int IP, string client, string server)
{
	if(server!=H)//如果server不是DHCP主机,则清除其待分配的IP。
	{
		for(int i=1;i<=N;i++)
		{
			if(IPs[i].state == 1&&IPs[i].user == client)
			{
				IPs[i].state = 0;
				IPs[i].T = 0;
				IPs[i].user = "";
			}
		}
		return;
	}
	if(!(IP>=1&&IP<=N && IPs[IP].user == client))
	{	//如果当前IP的user不是自己,则输出NAK
		cout<<H<<" "<<client<<" "<<"NAK"<<" "<<IP<<" "<<0<<endl;
	}
	else//否则按照要求改变IP的状态,并输出结果。
	{
		IPs[IP].state = 2;
		IPs[IP].user = client;
		ll tempt;
		if(T==0)
			tempt = ti+Tdef;
		else
		{
			tempt = T-ti;
			tempt = min(tempt, Tmax);
			tempt = max(tempt, Tmin);
			tempt = tempt+ti;
		}
		IPs[IP].T = tempt;
		cout<<H<<" "<<client<<" "<<"ACK"<<" "<<IP<<" "<<tempt<<endl;
	}
}

完整代码

#include<bits/stdc++.h>
#define ll long long
using namespace std;
struct IPinf
{
	ll state;
	ll T;
	string user;
};

ll N,Tdef,Tmax,Tmin;
string H;
IPinf IPs[10005];
void ini()
{
	for(int i=1;i<=N;i++)
	{
		IPs[i].state = 0;
		IPs[i].T = 0;
		IPs[i].user = "";
	}
}
void update(ll ti)
{
	for(int i=1;i<=N;i++)
	{
		if(IPs[i].T!=0 && IPs[i].T <= ti)
		{
			if(IPs[i].state == 1)
			{
				IPs[i].state = 0;
				IPs[i].T = 0;
				IPs[i].user = "";
			}
			else if(IPs[i].state == 2)
			{
				IPs[i].state = 3;
				IPs[i].T = 0;
			}
		}
	}
}
void DIS(ll ti, ll Tdef, ll T, string client)
{
	ll IP_to_client=0;
	int flag = 0;
	for(int i=1;i<=N;i++)
	{
		if(IPs[i].user == client)
		{
			IP_to_client = i;
			flag = 1;
			break;
		}
	}
	for(int i=1;i<=N &&flag == 0;i++)
	{
		if(IPs[i].state==0)
		{
			IP_to_client = i;
			flag = 2;
			break;
		}
	}
	for(int i=1;i<=N&&flag==0;i++)
	{
		if(IPs[i].state==3)
		{
			IP_to_client = i;
			flag = 3;
			break;
		}
	}
	if(flag == 0)
		return;
	ll tempt;
	if(T==0)
		tempt = ti+Tdef;
	else
	{
		tempt = T-ti;
		tempt = min(tempt, Tmax);
		tempt = max(tempt, Tmin);
		tempt = tempt+ti;
	}
	IPs[IP_to_client].state = 1;
	IPs[IP_to_client].user = client;
	IPs[IP_to_client].T = tempt;
	cout<<H<<" "<<client<<" "<<"OFR"<< " "<<IP_to_client<<" "<<tempt<<endl;
}

void REQ(ll ti, ll T, int IP, string client, string server)
{
	if(server!=H)
	{
		for(int i=1;i<=N;i++)
		{
			if(IPs[i].state == 1&&IPs[i].user == client)
			{
				IPs[i].state = 0;
				IPs[i].T = 0;
				IPs[i].user = "";
			}
		}
		return;
	}
	if(!(IP>=1&&IP<=N && IPs[IP].user == client))
	{
		cout<<H<<" "<<client<<" "<<"NAK"<<" "<<IP<<" "<<0<<endl;
	}
	else
	{
		IPs[IP].state = 2;
		IPs[IP].user = client;
		ll tempt;
		if(T==0)
			tempt = ti+Tdef;
		else
		{
			tempt = T-ti;
			tempt = min(tempt, Tmax);
			tempt = max(tempt, Tmin);
			tempt = tempt+ti;
		}
		IPs[IP].T = tempt;
		cout<<H<<" "<<client<<" "<<"ACK"<<" "<<IP<<" "<<tempt<<endl;
	}
}
int main()
{
	ios::sync_with_stdio(false);
	cin.tie(0);
	cout.tie(0);
	cin>>N>>Tdef>>Tmax>>Tmin>>H;
	int n;
	cin>>n;
	ini();
	while(n--)
	{
		ll ti;
		string client,server,type;
		ll IP, T;
		cin>>ti>>client>>server>>type>>IP>>T;
		if(!(server==H||(server=="*")))
		{
			if(type != "REQ")
				continue;
		}
		if(!(type=="REQ"||type=="DIS"))
			continue;
		if(((server == "*"&&type!="DIS") || (server==H&&type=="DIS")))
			continue;
		update(ti);
		if(type == "DIS")
		{
			DIS(ti,Tdef,T,client);
		}
		else if(type == "REQ")
		{
			REQ(ti,T,IP,client,server);
		}
	}
	return 0;
 } 
  • 1
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 1
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值