csp 2021-04-3 DHCP服务器

考场上看到这道题时,自己完全没有勇气去做,原因是以为要实现一个定时器记录时间,那岂不是要多线程???
今天仔细分析了一下,发现其实接收的数据报文中第一个值就是当前的时间,可以以此判断ip地址是否过期。。。
原题入口

#include <stdio.h>
#include <string.h>
#define MAX(x,y)  (((x)>(y))?(x):(y))
#define MIN(x,y)  (((x)<(y))?(x):(y))
typedef long long ll;
ll N, Tdef, Tmax, Tmin, mes_num;
char H[25];
char send[25], rec[25], type[20];
ll r_time, q_time, ip_address;
struct st {
	int state=0;	//0 未分配 1 待分配 2 占用 3 过期
	ll outtime=0;
	char owner[25]="";
}ip[10005];
void brush(){	//只更新状态即可,特定状态对应的属性值其实不用改
	ll i;		//检索的时候根据状态选定IP后,直接修改其他属性值
				//即不用核实状态与属性的一致性
				//但是对于未分配且过期的ip,由于检索时会比较占有者名称(33-36),因此也需要刷新
	for (i = 1; i <= N; i++)
		if (ip[i].outtime <= r_time)
		{
			if (ip[i].state == 2)
				ip[i].state = 3;
			if (ip[i].state == 1)
			{
				ip[i].state = 0;
				strcpy(ip[i].owner, "");
			}
		}
}
ll find_ip() {
	ll i;
	for (i = 1; i <= N; i++) {
		if (strcmp(send, ip[i].owner) == 0)	//前提是保证了状态与占用者属性的一致性。。
			return i;
	}
	for (i = 1; i <= N; i++) {
		if (ip[i].state == 0)
			return i;
	}
	for (i = 1; i <= N; i++) {
		if (ip[i].state == 3)
			return i;
	}
	return 0;
}
int deal() {
	if (strcmp(H, rec) != 0 && strcmp("*", rec) != 0) {
		if (strcmp(type, "REQ") != 0)
			return 0;
	}
	if (strcmp(type, "REQ") != 0 && strcmp(type, "DIS") != 0)
		return 0;
	if (strcmp("*", rec) == 0 && strcmp(type, "DIS") != 0 || strcmp(H, rec) == 0 && strcmp(type, "DIS") == 0)
		return 0;
	if (strcmp(type, "DIS") == 0) {
		ll f = find_ip();
		if (!f) return 0;//地址池耗尽
		ip[f].state = 1;
		strcpy(ip[f].owner, send);
		if (q_time == 0) {
			ip[f].outtime = r_time + Tdef;
		}
		else {
			ll newot = q_time;
			newot = MAX(r_time + Tmin, newot);
			newot = MIN(r_time + Tmax, newot);
			ip[f].outtime = newot;
		}
		/*else if (q_time >= Tmin + r_time && q_time <= Tmax + r_time) {
			ip[f].outtime = q_time;
		}
		else if (q_time < Tmin + r_time)
			ip[f].outtime = r_time + Tmin;
		else if (q_time > Tmax + r_time)
			ip[f].outtime = r_time + Tmax;*/
		printf("%s %s OFR %lld %lld\n", H, send, f, ip[f].outtime);
	}
	else if (strcmp(type, "REQ")==0) {
		ll i;
		if (strcmp(rec, H) != 0) {
			for (i = 1; i <= N; i++) {
				if (strcmp(ip[i].owner, send)==0) {
					if (ip[i].state == 1) {
						ip[i].state = 0;
						strcpy(ip[i].owner, "");
						//ip[i].outtime = 0;
					}
				}
			}
			return 0;
		}
		if (ip_address <= N && strcmp(ip[ip_address].owner, send) == 0) {
			ip[ip_address].state = 2;
			if (q_time == 0) {
				ip[ip_address].outtime = r_time + Tdef;
			}
			else {
				ll newot = q_time;
				newot = MAX(r_time + Tmin, newot);
				newot = MIN(r_time + Tmax, newot);
				ip[ip_address].outtime = newot;
			}
			/*else if (q_time >= Tmin+r_time && q_time <= Tmax+r_time) {
				ip[ip_address].outtime = q_time;
			}
			else if (q_time < Tmin+r_time)
				ip[ip_address].outtime = r_time + Tmin;
			else if (q_time > Tmax+r_time)
				ip[ip_address].outtime = r_time + Tmax;*/
			printf("%s %s ACK %lld %lld\n", H, send, ip_address, ip[ip_address].outtime);
		}
		else {
			printf("%s %s NAK %lld 0\n", H, send, ip_address);
			return 0;
		}
		return 1;
	}

}
int main() {
	scanf("%lld%lld%lld%lld%s", &N, &Tdef, &Tmax, &Tmin, H);
	scanf("%lld", &mes_num);
	while (mes_num--) {
		scanf("%lld%s%s%s%lld%lld", &r_time, send, rec, type, &ip_address, &q_time);
		brush();
		deal();
	}
	return 0;
}

思路就是按照实现细节一步一步处理,一定要仔细分析状态转换的逻辑,该同步的属性值最开始还是不要偷懒省去,很可能导致一些逻辑错误。

第一次做大模拟,大佬勿喷😋

  • 4
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值