背景
開發的產品需要增加 AutoIP 功能,具體要求如下:
-
當設置爲 DHCP 時,如果 DHCP 獲取或續約失敗,則啓用 AutoIP 獲取 IP 地址
-
AutoIP 期間,DHCP 一旦成功則切換到 DHCP 獲得的 IP 地址
介紹 Zeroconf
Zeroconf 全稱爲 Zero configuration networking,提出者是 Apple 公司,中文名則爲零配置網絡規範,是一種用於自動生成可用 IP 地址的網絡技術,不需要額外的手動配置和專屬的配置服務器
“零配置網絡服務”的目標,是讓非專業用戶也能便捷的連接各種網絡設備,例如計算機、打印機等。整個搭建網絡的過程都是通過程序自動化完成
如果沒有 Zeroconf,用戶必須手動配置一些服務,例如 DHCP、DNS、計算機網絡的其它設置等。這些對非技術用戶和新用戶們來說是很難的事情
很多 Linux 發行版都默認安裝該服務,當系統無法連接 DHCP server 的時候,就會嘗試通過 Zeroconf 來獲取 IP
舉個例子:
用戶擁有一臺 Apple TV 和一臺 iPhone X,它們只要都連入到同一個無線局域網內,iPhone X 就會自動找出 Apple TV,那麼在播放音樂或者視頻的時候,用戶只要點擊推送,就可以將音樂和視頻推送到 Apple TV 上播放
Zeroconf 既然是協議,因此對應的是各種產品的實現,現在最主要的實現是 Apple 公司的 Bonjour 和開源的 Avahi
介紹 Avahi
Avahi 是 Zeroconf 規範的開源實現,基本是使用在 Linux 和 FreeBSD 上。包含了一整套多播 DNS(multicast DNS)/DNS-SD 網絡服務的實現,使用的發佈授權是 LGPL。在程序接口上,它使用 DNSD 與 Apple 的 Bonjour 進行兼容,方便原來使用 Bonjour 的產品進行遷移
目前在絕大多數的 Linux 發行版本中,都將 Avahi 作爲系統啓動進程,並且大量的服務也依賴於avahi
Avahi 也是用純 C 編寫的,同樣也可以使用諸如 Java 語言去調用
Avahi 允許程序在不需要進行手動配置網絡的情況下,在一個本地網絡中發佈和獲知各種服務和主機。例如,當某用戶把他的計算機接入到某個局域網時,如果他的計算機運行有 Avahi 服務,則 Avahi 程序就會自動廣播,從而發現網絡中可用的打印機、共享文件和可相互聊天的其他用戶
接下來介紹在嵌入式怎麼使用 Avahi …
軟件包
下載所需的軟件包,avahi 需要依賴:
- expat,用於解析 XML 文件的 ( --with-xml=expat )
- libdaemon,編譯 avahi 必須的包,用於支持 avahi-daemon ( --enable-libdaemon )
http://distfiles.macports.org/expat/expat-2.1.0.tar.gz
http://distfiles.macports.org/libdaemon/libdaemon-0.14.tar.gz
http://distfiles.macports.org/avahi/avahi-0.6.31.tar.gz
例如,按照下圖的文件組織結構擺放好,編譯生成的頭文件和庫文件設定存放在 out 目錄
交叉編譯
先來看 expat,Makefile 如下,配置自己的交叉工具鏈,沒什麼需要特別注意的
export CROSS_COMPILE ?= arm-linux-
export CC := $(CROSS_COMPILE)gcc
export CXX := $(CROSS_COMPILE)g++
export AR := $(CROSS_COMPILE)ar
export RANLIB := $(CROSS_COMPILE)ranlib
export LD := $(CROSS_COMPILE)ld
export STRIP := $(CROSS_COMPILE)strip
export OBJCOPY := $(CROSS_COMPILE)objcopy
NAME = expat-2.1.0
PREFIX_DIR = $(shell pwd)/../out
default: clean
make install
clean:
rm -rf $(NAME)
unpack: clean
tar xzvf $(NAME).tar.gz
config: unpack
cd $(NAME) && ./configure\
--host=arm-linux\
--build=i686-linux\
--prefix=$(PREFIX_DIR)
build: config
make -C $(NAME)
install: build
make -C $(NAME) install
其次是 libdaemon
export CROSS_COMPILE ?= arm-linux-
export CC := $(CROSS_COMPILE)gcc
export CXX := $(CROSS_COMPILE)g++
export AR := $(CROSS_COMPILE)ar
export RANLIB := $(CROSS_COMPILE)ranlib
export LD := $(CROSS_COMPILE)ld
export STRIP := $(CROSS_COMPILE)strip
export OBJCOPY := $(CROSS_COMPILE)objcopy
NAME = libdaemon-0.14
PREFIX_DIR = $(shell pwd)/../out
default: clean
make install
clean:
rm -rf $(NAME)
unpack: clean
tar xzvf $(NAME).tar.gz
config: unpack
echo "ac_cv_func_setpgrp_void=yes" > $(NAME)/config.cache
cd $(NAME) && ./configure\
--host=arm-linux\
--build=i686-linux\
--config-cache\
--prefix=$(PREFIX_DIR)\
--disable-lynx
build: config
make -C $(NAME)
install: build
make -C $(NAME) install
再到 avahi,需要注意的是第 49 行,要加上prefix=""
纔行,否則運行不起來
運行 avahi 進程的時候,需要一個配置文件叫 avahi-autoipd.action
prefix=""
表示配置文件的路徑是在 /etc/avahi/avahi-autoipd.action
export CROSS_COMPILE ?= arm-linux-
export CC := $(CROSS_COMPILE)gcc
export CXX := $(CROSS_COMPILE)g++
export AR := $(CROSS_COMPILE)ar
export RANLIB := $(CROSS_COMPILE)ranlib
export LD := $(CROSS_COMPILE)ld
export STRIP := $(CROSS_COMPILE)strip
export OBJCOPY := $(CROSS_COMPILE)objcopy
NAME = avahi-0.6.31
PREFIX_DIR = $(shell pwd)/../out
default: clean
make install
clean:
rm -rf $(NAME)
unpack:
tar xzvf $(NAME).tar.gz
config: unpack
cd $(NAME) && ./configure\
--host=arm-linux\
--build=i686-linux\
--prefix=$(PREFIX_DIR)\
--disable-dbus\
--disable-gdbm\
--disable-glib\
--disable-gobject\
--disable-gtk\
--disable-gtk3\
--disable-manpages\
--disable-monodoc\
--disable-python\
--disable-qt3\
--disable-qt4\
--enable-libdaemon\
--with-distro=none\
--with-xml=expat\
--with-avahi-user=root\
--with-avahi-group=root\
--with-autoipd-user=root\
--with-autoipd-group=root\
CC=$(CC)\
CXX=$(CXX)\
LD=$(LD)\
RANLIB=$(RANLIB)\
CFLAGS="-I$(PREFIX_DIR)/include"\
CXXFLAGS="-I$(PREFIX_DIR)/include"\
LDFLAGS="-L$(PREFIX_DIR)/lib"\
PKG_CONFIG_PATH="$(PREFIX_DIR)/lib/pkgconfig"
build: config
make -C $(NAME) prefix=""
install: build
make -C $(NAME) install
最後到最外層的 Makefile,統攬全局,只需在最外層敲一個make
就可以編譯完
PREFIX_DIR = $(shell pwd)/out
default: clean
test -z $(PREFIX_DIR) || mkdir -p $(PREFIX_DIR)
make -C expat
make -C libdaemon
make -C avahi
clean:
make -C expat clean
make -C libdaemon clean
make -C avahi clean
準備環境
一塊開發板、一個交換機、一個路由器,按下圖連接好
爲了能快速驗證 autoip 的功能,我們把路由器的 DHCP 租約時間設置爲最小,本實驗所用路由器最小租約時間是 2 分鐘
正常的時候,PC 和開發板都是可以上外網的,當然也可以互相 ping 通
正常時 PC 的 IP 信息如下
正常時開發板的 IP 信息如下
實驗
把 out/lib 目錄的動態庫文件拷貝到開發板的 /lib 目錄
把 out/sbin 目錄的可執行文件拷貝到開發板的 /sbin 目錄
在開發板運行avahi-autoipd -h
查看幫助文檔可知,需要一個腳本
把 out/etc/avahi 目錄的配置文件 avahi-autoipd.action 拷貝到開發板的 /etc/avahi 目錄
運行 avahi-autoipd,命令是:
/sbin/avahi-autoipd -D eth0 --script=/etc/avahi/avahi-autoipd.action
這時候,拔掉上面連接圖的紅色這根網線,然後等待 2 分鐘左右,開發板會去請求 DHCP 續租,但是網線已被我們拔掉,請求已經達到不了路由器這邊了,所以這時候 autoip 會自動獲取一個 169.254.xxx.xxx 的地址,ifconfig 看到的地址信息如下圖
再看 PC 這邊的地址信息,因爲 PC 本身就內置了 Zeroconf 協議的實現,所以 PC 也會拿到一個 169.254.xxx.xxx 的地址,如下圖
此時,PC 和 開發板之間依然可以進行通信,因爲他們還在一個局域網裏頭
參考資料
https://www.xuebuyuan.com/3195396.html