• dhcp


    #include <iostream>
    #include <cstring>
    #include <string>
    #include <algorithm>
    
    using namespace std;
    
    const int N = 1e4 + 10;
    //四个正整数和一个字符串,分别是:、、、 和 ,
    int n, m, t_def, t_max, t_min;
    string h;
    struct IP
    {
    	int state; //0:未分配, 1:待分配, 2:占用, 3过期
    	int t;	//过期时间
    	string owner;	//占用者
    }ip[N];
    void update_ip(int t) {
    	/*处于待分配和占用状态的 IP 地址拥有一个大于零的过期时刻。
    	在到达该过期时刻时,
    	若该地址的状态是待分配,则该地址的状态会自动变为未分配,且占用者清空,过期时刻清零;
    	否则该地址的状态会由占用自动变为过期,且过期时刻清零。
    	处于未分配和过期状态的 IP 地址过期时刻为零,即没有过期时刻。*/
    	for (size_t i = 1; i <= n; i++){
    		if (ip[i].state == 1 && ip[i].t && ip[i].t <= t) {
    			ip[i].state = 0;
    			ip[i].owner = "";
    			ip[i].t = 0;
    		}
    		else if (ip[i].state == 2 && ip[i].t  && ip[i].t <= t) {
    			ip[i].state = 3;
    			ip[i].t = 0;
    		}
    		else if (ip[i].state == 0 || ip[i].state == 3) {	//细节
    			ip[i].t = 0;
    		}
    	}
    }
    int get_ip_by_owner(string owner) {
    	for (size_t i = 1; i <= n; i++)
    	{
    		if (ip[i].owner == owner)
    		{
    			return i;
    		}
    	}
    
    	return 0;
    }
    
    int get_ip_by_state(int state) {
    	for (size_t i = 1; i <= n; i++)
    	{
    		if (ip[i].state == state) {
    			return i;
    		}
    	}
    	return 0;
    }
    int main() {
    	cin >> n >> t_def >> t_max >> t_min >> h;
    	cin >> m;
    	while (m--){
    		//第  个报文是在  时刻收到
    		int t;
    		string client, server, type;
    		int id, te;//过期时刻
    		cin >> t >> client >> server >> type >> id >> te;
    		//否为本机,为 *,若不是,则判断类型是否为 Request,若不是,则不处理;
    		if (server != h && server != "*") {
    			if(type != "REQ")
    				continue;
    		}
    		//若类型不是 Discover、Request 之一,则不处理;
    		if (type != "DIS"&&type != "REQ")	continue;
    		//若接收主机为 *,但类型不是 Discover,或接收主机是本机,但类型是 Discover,则不处理。
    		if (server == "*"&&type != "DIS")	continue;
    		if (server == h && type == "DIS")	continue;
    		update_ip(t);
    		//对于 Discover 报文,按照下述方法处理:
    		if (type == "DIS") {
    			/*检查是否有占用者为发送主机的 IP 地址:
    				若有,则选取该 IP 地址;
    				若没有,则选取最小的状态为未分配的 IP 地址;
    				若没有,则选取最小的状态为过期的 IP 地址;
    				若没有,则不处理该报文,处理结束;*/
    			int k = get_ip_by_owner(client);
    			if (!k) k = get_ip_by_state(0);
    			if (!k) k = get_ip_by_state(3);
    			if (!k) continue;
    			//将该 IP 地址状态设置为待分配,占用者设置为发送主机;
    			ip[k].state = 1;
    			ip[k].owner = client;
    			/*
    			若报文中过期时刻为 0 ,则设置过期时刻为 t + t_def ;t
    			否则根据报文中的过期时刻和收到报文的时刻计算过期时间,
    			判断是否超过上下限:
    				若没有超过,则设置过期时刻为报文中的过期时刻;
    				否则则根据超限情况设置为允许的最早或最晚的过期时刻;*/
    			if (te == 0) {
    				te = t + t_def;
    			}
    			else {
    				if (te > t + t_max)	te = t + t_max;
    				else if (te < t + t_min)	te = t + t_min;
    			}
    			ip[k].t = te;//记得加过期时间
    			//向发送主机发送 Offer 报文,其中,IP 地址为选定的 IP 地址,过期时刻为所设定的过期时刻。
    			printf("%s %s OFR %d %d
    ", h.c_str(), client.c_str(), k, te);
    		}
    		//对于 Request 报文,按照下述方法处理
    		if (type == "REQ") {
    			/*
    			检查接收主机是否为本机:
    				若不是,则找到占用者为发送主机的所有 IP 地址,
    					对于其中状态为待分配的,将其状态设置为未分配,并清空其占用者,清零其过期时刻,处理结束;
    					*/
    			if (server != h) {
    				for (size_t i = 1; i <= n; i++){
    					if (ip[i].owner == client) {
    						if (ip[i].state == 1) {
    							ip[i].state = 0;
    							ip[i].owner = "";
    							ip[i].t = 0;
    						}
    					}
    				}
    				continue;
    			}
    			/*
    			检查报文中的 IP 地址是否在地址池内,且其占用者为发送主机,
    			若不是,则向发送主机发送 Nak 报文,处理结束;*/
    			if (id > n || id < 0 || ip[id].owner != client) {
    				//dhcp b NAK 2 0
    				printf("%s %s NAK %d 0
    ", h.c_str(), client.c_str(), id);
    				continue;
    			}
    			/*
    			无论该 IP 地址的状态为何,将该 IP 地址的状态设置为占用;
    			与 Discover 报文相同的方法,设置 IP 地址的过期时刻;
    			向发送主机发送 Ack 报文。*/
    			ip[id].state = 2;
    			if (te == 0) { //注意超时定义
    				te = t + t_def;
    			}
    			else {
    				if (te > t + t_max)	te = t + t_max;
    				else if (te < t + t_min)	te = t + t_min;
    			}
    			ip[id].t = te;
    			//dhcp c ACK 3 20
    			printf("%s %s ACK %d %d
    ", h.c_str(), client.c_str(), id, te);
    
    		}
    
    	}
    	return 0;
    
    }
    
  • 相关阅读:
    WPF 从文件加载字体
    WPF 从文件加载字体
    WPF 从文件加载字体
    win10 uwp 让焦点在点击在页面空白处时回到textbox中
    win10 uwp 让焦点在点击在页面空白处时回到textbox中
    win10 uwp 让焦点在点击在页面空白处时回到textbox中
    PHP date_parse_from_format() 函数
    PHP date_offset_get() 函数
    PHP date_modify() 函数
    PHP date_isodate_set() 函数
  • 原文地址:https://www.cnblogs.com/CSE-kun/p/15256874.html
Copyright © 2020-2023  润新知