• java实现通过DHCP协议获取IP地址


    前言

    DHCP(Dynamic Host Configuration Protocol),动态主机配置协议,是一个应用层协议。当我们将客户主机IP地址设置为动态获取方式时,DHCP服务器就会根据DHCP协议给客户端分配IP,使得客户端机器能够利用这个IP上网。我们的电脑和手机使用WIFI的时候,都是使用DHCP协议来获取IP的。

    ipconfig /all
    

    windows系统下,我们可以使用上面的命令查看IP的获取方式和DHCP服务器地址。

    分配原理

    1. DHCP客户端以广播的方式发出Discover报文。
    2. 所有的DHCP服务器都能够接收到此报文,都会给出响应,向客户端发送一个Offer报文。该报文中包含提供给客户端使用的IP地址,也包含服务器自己的IP地址,以便客户端区分不同的服务器。服务器在发出此报文后会保存一个已分配IP地址的纪录。
    3. 客户端只能处理其中的一个Offer报文,一般的原则是处理最先收到的报文。客户端再次以广播的方式发出Request报文,会包含选中的服务器的IP地址和需要的IP地址。
    4. 服务器收到Request报文后,判断其中服务器的IP地址是否与自己的地址相同。如果不相同,不做任何处理只清除相应IP地址分配记录,如果相同,就会向客户端响应一个ACK报文,其中会包含IP地址的使用租期信息(可以参考上面ipconfig命令的结果)。
    5. 客户端接收到ACK报文后,检查服务器分配的IP地址是否能够使用。如果可以使用,则客户端成功获得IP地址并根据IP地址使用租期自动启动续延过程,如果发现分配的IP地址已经被使用,则向服务器发出Decline报文,通知服务器禁用这个IP地址,然后客户端开始新的IP申请过程。
    6. 客户端在成功获取IP地址后,随时可以通过发送Release报文释放自己的IP地址,服务器收到Release报文后,会回收相应的IP地址并重新分配。

    更多工作原理相关,查看DHCP百度百科

    代码实现

    maven依赖

    <dependency>
      <groupId>com.helger</groupId>
      <artifactId>dhcp4java</artifactId>
      <version>1.1.0</version>
    </dependency>
    
    import java.io.IOException;
    import java.net.DatagramPacket;
    import java.net.DatagramSocket;
    import java.net.InetAddress;
    import org.dhcp4java.DHCPConstants;
    import org.dhcp4java.DHCPPacket;
    import org.dhcp4java.HardwareAddress;
    
    public class DHCPTest {
    
      public static void main(String[] args) throws IOException {
    
        //当前电脑的物理地址
        byte[] macAddress = HardwareAddress.getHardwareAddressByString("5C:80:B6:FD:91:A7")
            .getHardwareAddress();
        //封装DHCP请求包
        DHCPPacket discover = new DHCPPacket();
        //发送DISCOVER报文
        discover.setOp(DHCPConstants.DHCPDISCOVER);
        //硬件类别为以太网
        discover.setHtype(DHCPConstants.HTYPE_ETHER);
        //硬件地址长度 以太网为6
        discover.setHlen((byte) 6);
        //局域网为0
        discover.setHops((byte) 0);
        //请求ID
        discover.setXid(123);
        //客户端启动时间(秒)
        discover.setSecs((short) 10000);
        discover.setFlags((short) 0);
        //客户端的硬件地址
        discover.setChaddr(macAddress);
        //消息类型
        discover.setDHCPMessageType(DHCPConstants.DHCPDISCOVER);
        //客户端请求服务器的68端口,服务器请求客户端的67端口
        DatagramSocket socket = new DatagramSocket(DHCPConstants.BOOTP_REPLY_PORT);
        byte[] discoverBytes = discover.serialize();
        DatagramPacket sendPacket = new DatagramPacket(discoverBytes,
            discoverBytes.length,
            InetAddress.getByName("255.255.255.255"), DHCPConstants.BOOTP_REQUEST_PORT);
        //发送请求报文
        socket.send(sendPacket);
        DatagramPacket receivePacket = new DatagramPacket(new byte[1500], 1500);
        //接收服务器的响应报文
        socket.receive(receivePacket);
        DHCPPacket resultDhcpPacket = DHCPPacket.getPacket(receivePacket);
        //返回报文包含macAddress
        if (bytesToHexString(resultDhcpPacket.getChaddr()).contains(
            bytesToHexString(macAddress))) {
          //获取的IP地址
          System.out.println(resultDhcpPacket.getYiaddr());//192.168.0.142
        }
        socket.close();
      }
    
      private static String bytesToHexString(byte[] src) {
        StringBuilder stringBuilder = new StringBuilder();
        for (byte b : src) {
          int v = b & 0xFF;
          String hv = Integer.toHexString(v);
          if (hv.length() < 2) {
            stringBuilder.append(0);
          }
          stringBuilder.append(hv);
        }
        return stringBuilder.toString();
      }
    
    }
    

    查看当前电脑的物理地址,5C:80:B6:FD:91:A7

    参考

    DHCP百度百科
    java实现DHCP协议获取ip地址
    java 探测网络中是否有dhcp环境
    Wireshark分析DHCP

  • 相关阅读:
    WCF进行大数据传输时的相关配置(转)
    自定义绑定(转)
    菜鸟学TSQLSQL2005读书笔记1
    再别康桥英文及译文
    自定义绑定2
    我要读的书
    菜鸟学TSQLSQL2005读书笔记
    Bad Habbits
    实践测试驱动开发
    针对接口写测试用例
  • 原文地址:https://www.cnblogs.com/strongmore/p/16027930.html
Copyright © 2020-2023  润新知