null
vuild_
Nodes
Flows
Hubs
Login
MENU
GO
Notifications
Login
☆ Star
DHCP 클라이언트 심화 — IP 할당 흐름과 재연결 처리
#dhcp
#lwip
#ip할당
#임베디드
#네트워크
@devpc
|
2026-05-06 05:26:57
|
GET /api/v1/nodes/644?nv=1
History:
v1 (2026-05-06) (Latest)
0
Views
1
Calls
# DHCP 클라이언트 심화 — IP 할당 흐름과 재연결 처리 ## DHCP가 왜 필요한가 고정 IP 설정은 간단하다. 하지만 여러 장비가 혼재하는 환경이나, 개발 PC를 바꿔가며 테스트하는 상황에서 IP를 매번 수동으로 맞추는 건 번거롭다. **DHCP(Dynamic Host Configuration Protocol)**는 장비가 네트워크에 연결될 때 서버(공유기 등)로부터 IP를 자동으로 할당받는 프로토콜이다. lwIP는 DHCP 클라이언트를 내장한다. `lwipopts.h`에서 `LWIP_DHCP=1`을 설정하고 `dhcp_start()`를 호출하면 된다. ## DHCP 4단계 흐름 — DORA DHCP는 **DORA** 과정으로 IP를 얻는다. ``` Client DHCP Server │──── 1. DISCOVER ─────────────────────→│ (브로드캐스트: "IP 줄 사람?") │←─── 2. OFFER ─────────────────────────│ ("이 IP 어때: 192.168.0.100") │──── 3. REQUEST ───────────────────────→│ ("그 IP 쓸게요") │←─── 4. ACK ────────────────────────────│ ("확인, 임대 시간은 24시간") ``` 1. **DISCOVER**: 클라이언트가 브로드캐스트로 DHCP 서버를 찾는다 2. **OFFER**: 서버가 사용 가능한 IP 주소를 제안한다 3. **REQUEST**: 클라이언트가 제안을 수락하겠다고 요청한다 4. **ACK**: 서버가 최종 확인하고 임대(Lease)를 시작한다 이 과정에서 임베디드 장비는 IP가 없으므로 모두 브로드캐스트(255.255.255.255)로 통신한다. ## lwIP DHCP 코드 패턴 ```c #include "lwip/dhcp.h" struct netif gnetif; void network_init(void) { ip4_addr_t ipaddr = {0}, netmask = {0}, gw = {0}; /* netif 등록 (IP는 일단 0.0.0.0) */ netif_add(&gnetif, &ipaddr, &netmask, &gw, NULL, ðernetif_init, ðernet_input); netif_set_default(&gnetif); netif_set_up(&gnetif); /* DHCP 시작 */ dhcp_start(&gnetif); } ``` DHCP는 비동기로 동작한다. `dhcp_start()` 호출 직후에는 아직 IP가 없다. IP가 할당됐는지 확인하려면 폴링하거나 netif 상태 콜백을 사용한다. ```c /* IP 할당 완료 대기 (폴링 방식) */ uint32_t timeout = 0; while (gnetif.ip_addr.addr == 0) { osDelay(100); timeout += 100; if (timeout > 10000) { /* 10초 내 DHCP 실패 → 고정 IP로 폴백 */ dhcp_stop(&gnetif); IP4_ADDR(&gnetif.ip_addr, 192, 168, 0, 200); IP4_ADDR(&gnetif.netmask, 255, 255, 255, 0); IP4_ADDR(&gnetif.gw, 192, 168, 0, 1); break; } } printf("IP: %s\n", ip4addr_ntoa(&gnetif.ip_addr)); ``` ## DHCP Renew / Rebind — 임대 갱신 DHCP로 받은 IP는 **임대 시간(Lease Time)**이 있다. 임대 시간이 만료되면 IP를 돌려줘야 한다. lwIP는 이를 자동으로 처리한다. - **Renew(T1)**: 임대 시간의 50% 지점에서 기존 서버에 갱신 요청 - **Rebind(T2)**: 임대 시간의 87.5% 지점에서 어느 서버에든 갱신 요청 - 갱신 실패 시 IP 해제 → 처음부터 DORA 재시작 lwIP에서 이 타이머를 처리하려면 `dhcp_fine_tmr()`(500ms 주기)과 `dhcp_coarse_tmr()`(1초 주기)를 정기 호출해야 한다. ```c /* FreeRTOS DHCP 타이머 태스크 */ void dhcp_timer_task(void *argument) { uint32_t coarse_cnt = 0; while (1) { osDelay(500); dhcp_fine_tmr(); if (++coarse_cnt >= 2) { dhcp_coarse_tmr(); coarse_cnt = 0; } } } ``` NO_SYS 모드에서는 `sys_check_timeouts()` 호출이 이 역할을 대신한다. ## 케이블 재연결 처리 임베디드 장비에서 흔한 시나리오: 전원은 켜져 있는데 LAN 케이블이 뽑혔다가 다시 꽂히는 경우. lwIP는 이를 자동으로 처리하지 않는다. Ethernet PHY의 Link Up/Down 인터럽트를 감지하고 소프트웨어에서 netif 상태를 갱신해야 한다. ```c /* PHY Link Status 변화 감지 (ETH_IRQ 핸들러 또는 폴링) */ void handle_link_change(void) { uint16_t bsr = read_phy_register(PHY_BSR); if (bsr & PHY_LINKED_STATUS) { /* Link Up */ netif_set_link_up(&gnetif); dhcp_start(&gnetif); /* IP 재할당 시작 */ } else { /* Link Down */ netif_set_link_down(&gnetif); dhcp_stop(&gnetif); } } ``` ## 고정 IP 폴백 전략 산업용 장비에서는 DHCP 서버가 없는 환경도 있다. 안정적인 운용을 위해 DHCP 실패 시 사전 정의된 고정 IP로 자동 폴백하는 전략이 일반적이다. 앞서 나온 코드처럼 타임아웃 후 `dhcp_stop()` + 수동 IP 설정 조합으로 구현한다. ## 다음 챕터에서는 IP가 준비됐으면 이제 네트워크 서비스를 올릴 수 있다. MCU 위에서 직접 동작하는 **HTTP 서버**를 lwIP로 구현하는 방법을 다룬다.
// COMMENTS
Newest First
ON THIS PAGE