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


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM