题目描述
DHCP服务器的功能是为每一个MAC地址分配唯一的IP地址。现假设:分配的IP地址范围从 192.168.0.0 到 192.168.0.255 总共256个可用地址(以点分十进制表示)。请实现一个简易的DHCP服务器,功能如下:
- 分配Request:根据输入的MAC地址分配IP地址池中的IP地址:
- 如果对应的IP已分配并未释放,则为重复申请,直接返回对应已分配的IP地址。
- 如果一个MAC地址已申请过并已释放,即:当前未分配IP地址,则为再申请,优先分配最近一次曾经为其分配过的IP地址,请返回此地址。
- 按升序分配从未被分配过的IP地址;如果地址池中地址都已被分配过,则按升序分配已释放出来的IP地址;若可分配成功,则返回此IP地址。
- 若仍然无法分配成功,则返回
NA
。
- 释放Release:根据输入的MAC地址释放已分配的IP地址:
- 如果申请释放的对应的IP地址已分配,则释放此IP地址;
- 如果申请释放的对应的IP地址不存在,则不作任何事情;
首行为整数n, 表示其后输入的命令行数,范围[1,2000]。
之后每行为一条分配命令,格式为:命令=MAC地址
- 命令只有两种:
REQUEST
和RELEASE
,分别表示分配和释放; - MAC地址为:12个大写英文字母或数字,如:
AABBCCDDEEF1
。
1.REQUEST命令,输出分配结果(IP地址字符串或字符串NA
),均为字符串形式。
注意:IP地址的各区段不设置前置
0
2.RELEASE命令,不输出任何内容。
样例输入样例 1 复制
2 REQUEST=AABBCCDDEEF1 RELEASE=AABBCCDDEEF1
输出样例 1
192.168.0.0提示样例 1
REQUEST=AABBCCDDEEF1 按升序分配从未使用过的IP地址,输出192.168.0.0
RELEASE=AABBCCDDEEF1 不输出
输入样例 2 复制
6 REQUEST=AABBCCDDEEF1 REQUEST=F2FBBCCDDEEF RELEASE=AABBCCDDEEF1 RELEASE=F2FBBCCDDEEF REQUEST=333333333333 REQUEST=F2FBBCCDDEEF
输出样例 2
192.168.0.0 192.168.0.1 192.168.0.2 192.168.0.1提示样例 2
REQUEST=AABBCCDDEEF1 按升序分配从未使用过的IP,为192.168.0.0
REQUEST=F2FBBCCDDEEF 按升序分配从未使用过的IP,为192.168.0.1
RELEASE=AABBCCDDEEF1 释放IP 192.168.0.0。
RELEASE=F2FBBCCDDEEF 释放IP 192.168.0.1。
REQUEST=333333333333 按升序分配从未使用过的IP,为192.168.0.2
REQUEST=F2FBBCCDDEEF 该MAC地址再申请,优先分配最近一次曾经为其分配过的IP,为192.168.0.1
提示
答题要求:结果可信和过程可信同样重要,您编写的代码需要符合可信的要求(包括通用编码规范、安全编码规范和圈复杂度)。
##############passs############## /* * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. * Description: 考生实现代码 * Note: 缺省代码仅供参考,可自行决定使用、修改或删除 * 只能import Go标准库 */ package main import ( "bufio" "fmt" "io" "os" "strconv" "strings" ) type ipMac struct { ip string mac string state string } type dhcpServer struct { ipMacs map[string]*ipMac macIps map[string]*ipMac } // 待实现函数,在此函数中填入答题代码 func constructor() dhcpServer { return dhcpServer{ ipMacs: make(map[string]*ipMac), macIps: make(map[string]*ipMac), } } // 待实现函数,在此函数中填入答题代码。 func (d *dhcpServer) release(mac string) { macIp, exist := d.macIps[mac] if !exist { return } if macIp.state == "used" { macIp.state = "free" } } // 待实现函数,在此函数中填入答题代码。 func (d *dhcpServer) request(mac string) string { // mac是否存已分配ip if macIp, exist := d.macIps[mac]; exist { //重复申请,直接返回ip if macIp.state == "used" { //fmt.Println("used oldMacIp",macIp, mac) return macIp.ip } // 已申请并已释放,申请最近一次使用过的ip if macIp.state == "free" { macIp.state = "used" // fmt.Println("oldMacIp",macIp, mac) return macIp.ip } } // 优先分配没有用的 for i:=0; i< 256; i++ { strLastIp := strconv.Itoa(i) endIp := "192.168.0." + strLastIp _, exist := d.ipMacs[endIp]; //fmt.Println("i am here", endIp) if !exist { ipMacObj := &ipMac{endIp,mac, "used"} d.macIps[mac] = ipMacObj d.ipMacs[endIp] = ipMacObj return endIp } } // 全部分配,按升序分配释放的ip for i:=0; i< 256; i++ { strLastIp := strconv.Itoa(i) endIp := "192.168.0." + strLastIp //fmt.Println("i am here111", endIp) if d.ipMacs[endIp].state == "free" { delete(d.macIps, d.ipMacs[endIp].mac) delete(d.ipMacs, endIp) ipMacObj := &ipMac{endIp, mac, "used"} d.macIps[mac] = ipMacObj d.ipMacs[endIp] = ipMacObj return endIp } } return "NA" } func main() { var n int if _, err := fmt.Scanf("%d", &n); err != nil { return } miniDhcpServer := constructor() inputReader := bufio.NewReader(os.Stdin) for i := 0; i < n; i++ { cmd, err := getCmd(inputReader, "=") if err != nil || len(cmd) != 2 { return } if cmd[0] == "REQUEST" { fmt.Println(miniDhcpServer.request(cmd[1])) } else if cmd[0] == "RELEASE" { miniDhcpServer.release(cmd[1]) } } } func getCmd(reader *bufio.Reader, sep string) ([]string, error) { lineBuf, err := reader.ReadString('\n') if err != nil && err != io.EOF { return nil, err } str := strings.TrimRight(lineBuf, "\r\n") return strings.Split(str, sep), nil } ###################ip池################# /* * Copyright (c) Huawei Technologies Co., Ltd. 2020-2020. All rights reserved. * Description: 考生实现代码 * Note: 缺省代码仅供参考,可自行决定使用、修改或删除 * 只能import Go标准库 */ package main import ( "bufio" "fmt" "io" "os" "strings" ) type ipMac struct { ip uint32 mac string } type ipMacs []ipMac type dhcpServer struct { ipPool []uint32 used ipMacs free ipMacs } // 待实现函数,在此函数中填入答题代码 func constructor() dhcpServer { d := dhcpServer{} d.ipPool = make([]uint32, 0, 256) d.used = make([]ipMac, 0, 256) d.free = make([]ipMac, 0, 256) for i := 0; i < 256; i++ { ip := uint32((192 << 24) | (168 << 16) | i) d.ipPool = append(d.ipPool, ip) } return d } // 待实现函数,在此函数中填入答题代码。 func (d *dhcpServer) request(mac string) string { // mac已分配还未释放直接返回对应的ip for _, v := range d.used { if v.mac == mac { return htoa(v.ip) } } // mac已申请且已释放,当再申请时优先分配 for i, v := range d.free { if v.mac == mac { d.used = append(d.used, d.free[i]) d.free = append(d.free[:i], d.free[i+1:]...) return htoa(v.ip) } } // 按升序分配未被分配的ip,再按已释放的地址升序分配地址 if len(d.ipPool) == 0 { if len(d.free) == 0 { return "NA" } min := minIp(d.free) ip := d.free[min] d.used = append(d.used, ipMac{ip.ip, mac}) d.free = append(d.free[:min], d.free[min+1:]...) return htoa(ip.ip) } ip := d.ipPool[0] d.used = append(d.used, ipMac{ip, mac}) d.ipPool = d.ipPool[1:] return htoa(ip) } // 待实现函数,在此函数中填入答题代码。 func (d *dhcpServer) release(mac string) { // 若已分配则释放 for i, v := range d.used { if v.mac == mac { d.free = append(d.free, v) // 从used中删除 d.used = append(d.used[:i], d.used[i+1:]...) return } } // 若已释放则什么也不做 } func htoa(ip uint32) string { return fmt.Sprintf("%d.%d.%d.%d", ip>>24, (ip>>16)&0xff, (ip>>8)&0xff, ip&0xff) } func minIp(ips ipMacs) int { if len(ips) == 1 { return 0 } min := 0 for i := 1; i < len(ips); i++ { if ips[min].ip > ips[i].ip { min = i } } return min } func main() { var n int if _, err := fmt.Scanf("%d", &n); err != nil { return } miniDhcpServer := constructor() inputReader := bufio.NewReader(os.Stdin) for i := 0; i < n; i++ { cmd, err := getCmd(inputReader, "=") if err != nil || len(cmd) != 2 { return } if cmd[0] == "REQUEST" { fmt.Println(miniDhcpServer.request(cmd[1])) } else if cmd[0] == "RELEASE" { miniDhcpServer.release(cmd[1]) } } } func getCmd(reader *bufio.Reader, sep string) ([]string, error) { lineBuf, err := reader.ReadString('\n') if err != nil && err != io.EOF { return nil, err } str := strings.TrimRight(lineBuf, "\r\n") return strings.Split(str, sep), nil }View Code
###感受###
1.一定要懂题意
2.已申请并已释放,申请最近一次使用过的ip:结合每一个MAC地址分配唯一的IP地址,就直接看是否在map中就可以了
3.注意标点符号断句:按升序分配从未被分配过的IP地址;最后是分号,代表一个条件完了。直接考虑下一个条件即可
4.注意看描述设计结构:如果地址池中地址都已被分配过, 隐含了一个结构,ip地址池,有3中状态,空,占用,释放
标签:return,err,上机,ip,编程,192.168,IP地址,DHCP,分配 From: https://www.cnblogs.com/gongxianjin/p/17894449.html