首页 > 编程语言 >上机编程-简易DHCP服务器

上机编程-简易DHCP服务器

时间:2023-12-11 15:14:10浏览次数:29  
标签:return err 上机 ip 编程 192.168 IP地址 DHCP 分配

题目描述

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地址不存在,则不作任何事情;
解答要求时间限制:1000ms, 内存限制:64MB 输入

首行为整数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

相关文章

  • 无涯教程-MFC - 网络编程
    Microsoft提供了许多用于对客户端和服务器应用程序进行编程的API,正在为互联网编写许多新应用程序,并且随着技术,浏览器功能和安全选项的变化,将编写新类型的应用程序。MFC提供了一个CSocket类,用于使用WindowsSockets编写网络通信程序。这是CSocket类中方法的列表。Sr.No.Name......
  • Java并发编程的高级探索
    随着多核处理器的普及,Java并发编程变得越来越重要。为了充分利用硬件资源,开发者需要掌握并发模式和算法、锁的优化技术、并发工具的高级应用,以及并发程序的性能分析方法。并发模式和算法在并发编程中,特定的模式和算法可以帮助我们解决一些复杂的问题:生产者-消费者模式:在多线程环境......
  • DHCP1.2 华三-DHCP中继配置(DHCP server在核心设备上做)
    公司比较大的话,核心层不止只有一个,比如A和B都是核心层的交换机,但是DHCPserver服务器是挂载在A区。(一般DHCPserver都是微软的windowserver服务器搭建DHCP)本实验仍旧DHCPserver在核心设备上建立。实在模拟不出用微软的DHCP建立。1.实验拓扑第一步:A区核心设备配置DHCPserver创建......
  • Java网络编程-深入理解BIO、NIO
    深入理解BIO与NIOBIOBIO为Blocked-IO(阻塞IO),在JDK1.4之前建立网络连接时,只能使用BIO使用BIO时,服务端会对客户端的每个请求都建立一个线程进行处理,客户端向服务端发送请求后,先咨询服务端是否有线程响应,如果没有就会等待或者被拒绝BIO基本使用代码:服务端:publicclassTCPServ......
  • DHCP
    DHCP动态主机配置协议DHCP:动态主机配置协议,实现终端设备的网络参数自动配置和管理,减轻管理员工作量,便于管理,降低客户端的配置和维护成本            采用C/S架构(服务器和客户端架构),基于UDP封装,67端口号标识服务器,68端口号标识客户端DHCP报文(工作流程):         ......
  • #yyds干货盘点#深入了解Python类与面向对象编程
    类与对象的概念1.什么是类?类是一种用户自定义的数据类型,用于描述对象的属性和行为。它是对象的模板,定义了对象的结构。2.创建类使用class关键字来创建类。示范如何定义一个类,包括类名、属性和方法的定义。classDog:def__init__(self,name,breed):self.name=nam......
  • TIOBE 12月榜单: C# 即将成为2023 年度编程语言
    TIOBE公布了2023年12月的编程语言排行榜。2022年C#在挑战成为年度编程语言,但在最后一刻,C++出人意料地夺得了冠军。今年,我们确信C#将获胜成为2023年度编程语言。它在1年内上涨了2.38%,而其最接近的竞争者Fortran和F#分别仅上涨了+0.64%和+0.48%。TIOBE的10月份榜......
  • 【教3妹学编程-算法题】需要添加的硬币的最小数量
    3妹:2哥2哥,你有没有看到新闻,有人中了2.2亿彩票大奖!2哥 :看到了,2.2亿啊,一生一世也花不完。3妹:为啥我就中不了呢,不开心呀不开心。2哥 :得了吧,你又不买彩票,还是脚踏实地的好~3妹:小富靠勤,中富靠德,大富靠命,可能是我命不好。2哥 :哎,想我口袋只有几个硬币,叮咚作响。3妹:说到硬币,我......
  • 用元编程来判断STL类型
      在此之前,先来回顾元编程当中的一个重要概念。template<typename_Tp,_Tp__v>structintegral_constant{staticconstexpr_Tpvalue=__v;typedef_Tpvalue_type;typedefintegral_constant<......
  • 深入探究 Python 异步编程:利用 asyncio 和 aiohttp 构建高效并发应用
    在现代编程中,异步编程已成为处理高并发和IO密集型任务的重要方式。Python提供了强大的异步编程支持,包括asyncio库和aiohttp等框架。本文将深入探讨异步编程的概念,以及在Python中如何利用异步框架来实现高效的并发编程。1.异步编程概念异步编程允许程序在等待IO操作完成时......