IPv4地址集合里有兩個特殊地址:0.0.0.0、127.0.0.1,你是否了解他們的用途?輸入netstat -ano找到前面幾行有LISTEN標注的行,它表示本地系統開放的TCP4服務,文稿里顯示本地已開放38127、111、37681等端口,這些端口外部都能訪問嗎?為什么有些端口前面是0.0.0.0,有些卻是127.0.0.1呢?
如果你能輕易回答上面的問題,你已經不是網絡基礎小白 , 可以跳過這篇文章 , 單如果你不能 , 我想下面的工程實踐能給你解釋清楚 。另外你還能學到我的排查思路 。

文章插圖
基本解釋127.0.0.1叫 本地環回地址 ,用于測試協議棧的正確性,它不依賴硬件上是否有接網卡,它不依賴硬件上是否有接網卡,相當于用一根看不見的網線將網卡的發送和接收相連接起來 。
0.0.0.0叫 任意地址 ,若某以太網設備存在多塊物理網卡,表示只要本地開放對應的端口服務 , 無論從哪個網卡發起連接請求都是允許的 。若想限制某服務只允許外部設備從指定網卡入口發起訪問,則配置成具體網卡的IP地址,就如文稿插圖箭頭那行,8081端口只允許從IP地址為192.168.2.3的網卡入口發起 。
在編寫IPv4 TCP應用程序時候,執行綁定(bind)地址和端口組成服務,下圖文稿INADDR_ANY參數最為常用 , 綁定“任意地址” 。本文接下來內容講述,當綁定地址非INADDR_ANY時會引起什么現象、以及如何排查和解決 。

文章插圖
真實場景排查我前些天搭建MQTT平臺mosquitto時遇到個問題: 服務器只能向自己的環回地址 127.0.0.1地址發起連接 , 連接本地地址192.168.81.198則失敗 。問題的原因就與缺省路由有關 。
編譯好ARM平臺下的mosquitto之后,我當然會在ARM上測試一服務是否正常,顯然是成功的,同樣我把測試程序拷貝到其它主機上運行,客戶端提示不可連接(Unable to connect),服務器界面也沒有任何異常信息打印 。嵌入式工程師祖傳DNA有了反應: “It work on my machine”。首先兩端都執行ping命令排查網絡連接狀態,排除防火墻、路由表的配置,都沒看出明顯異常 。
接著我決定在服務器上再自己測試一次,只不過這次換成本地網卡地址 。
strace登??!没抓到accept注釋掉客戶端之前環回地址代碼,修改HOST為本地網卡地址192.168.81.198,重新編譯執行 。
// #define HOST "localhost"// #define HOST "127.0.0.1"#define HOST "192.168.81.198"嘿~同樣提示Unable to connect,活久見,自己訪問自己的服務居然也會失敗! 莫非是權限不足被服務器拒絕導致? 為探尋服務器究竟做了什么 , 我用strace mosquitto重新啟動服務器,試圖抓取到應用程序執行軌跡 , 屏幕有規律地滾動著epoll_wait信息,暗示服務器進入epoll循環 。在客戶端答應Unable to connect時strace沒抓取到服務器任何打破規律的系統調用,比如說TCP必須用到的accept 。

文章插圖
為證明發生正常連接情況下,服務器會執行系統調用accept,我重新修改HOST為127.0.0.1后再次用strace抓取 , 果不其然看到accept的身影(你可在文稿圖標注的步驟4中看到它) 。
【當你有多塊網卡會發生什么 網卡是什么】由此可知,當向網卡地址192.168.81.198發起連接時,服務器應用程序根本沒收到協議棧的數據,接著我再打開Wireshark抓取TCP數據 , 探尋數據交互過程究竟發生了什么 。

文章插圖
Wirshark登場!RST、ACKWireshark默認截獲物理網卡數據,物理網卡是下圖的wlp3s0,雖然實驗向本地網卡地址192.168.81.198發起連接,而在實際上數據并沒有“經過物理網卡”,在協議棧里路由選擇后切換成環回地址的路由 。
Wireshark操作界面選擇抓取接口Loopback:lo 。

文章插圖
對比客戶端分別向127.0.0.1和192.168.81.198發起連接的截獲情況 。連接環回地址可成功完成三次握手( 對應序號21:SYN;22:SYN、ACK;23:ACK),向連接本地網卡連接卻被復位(對應序號15:SYNC;16:RST、ACK) 。

文章插圖

文章插圖
復位連接的原因要么是不存在此IP,要么服務器沒啟動、此端口上不存在服務 , 要么連接被防火墻過濾 。鑒于前面已經排除防火墻可能,剩下的極有可能是本地服務器socket設置咯,輸入 “netstat -ano | grep 1883” 查看MQTT監聽端口狀態 。
原因找到了,本地監聽地址是127.0.0.1:1883 , 而非0.0.0.0:1883,所以任何外部連接都被拒絕 。

文章插圖
解決怎么處理呢?測試環境下mosquitto是不帶任何參數的,想必可以傳遞參數、配置文件靈活的更改mosquitto的特性 。注意到另外一臺x86平臺Linux系統上已經搭建好mosquitto , ps -aux查看mosquitto的啟動參數, “mosquitto -c /etc/mosquitto/mosquitto.conf”。x86平臺下的mosquitto.conf文件內容短小且沒有任何注釋信息,也沒看到看似監聽配置的關鍵詞 。
同目錄下還有另一個文件 mosquitto.conf.example,他的內容要豐富得多,有詳細的介紹 。
On systems that support Unix Domain Sockets, it is also possible to create a Unix socket rather than opening a TCP socket. In this case, the port number should be set to 0 and a unix socket path must be provided, e.g. listener 0 /tmp/mosquitto.sock
listener port-number [ip address/host name/unix socket path]
按照說明,重新編輯mosquitto.conf.example文件添加下面兩行,配置文件傳遞給服務器應用程序解析,netstat查詢到0.0.0.0:1883監聽,最后連接本地地址192.168.81.198成功 。
# mosquitto.conf.examplelistener 1883 0.0.0.0allow_anonymous true
文章插圖

文章插圖
- 《人民的名義》程度去省廳當辦公室副主任,是升職還是降級?
- 空運當中各種費用的縮寫是什么意思 空運當中各種費用的縮寫的意思是什么
- 怎樣恰當地稱贊別人 如何恰當地稱贊別人
- 食品安全標準涉及哪些方面 食品安全標準應當包括哪些內容
- 北京麥當勞優惠券
- friendships
- 汶川地震豬堅強
- 當深圳地名遇到生僻字 草字頭加今念什么
- 當時年少春衫薄
- 當山峰沒有棱角的時候
