Python 如何找到綁定的 IP 位址?
使用 Python 建立 Socket 物件並綁定 (bind) 到網卡後,該如何取得實際綁定的 IP 位址?這個問題多數人都會覺得簡單,但真的有這麼容易嗎?
問題描述
在 Python 網路服務器程式中,假設使用 UDP
協定的話,通常可以看到類似下面程式片段用來綁定 socket:
1 | self._socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
這樣的程式碼稀鬆平常,但您知道該如何取得實際綁定的本地 IP 位址嗎?
查了一下參考資料,您很快就會發現 Socket 物件有個 ‘getsockname’
方法可以回傳位址跟 port。
1 | ip, port = self._socket.getsockname() |
正當您覺得簡單完成任務的時候,卻發現 ‘ip’ 變數得到的是
‘0.0.0.0’,跟當初綁定用的值相同! 試了 ‘127.0.0.1’
也都是同樣的情況,怎麼會這樣?顯然 ‘getsockname’
的實作跟我們的期待完全不同。
解決方案
下面程式片段示範如何取的本地網卡所使用的 IP 位址跟埠號 (port):
1 | s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM) |
其中標記 1
的地方是整個片段可以運作的關鍵。另外,上述程式片段有可能會丟出 IOError
的例外,請記得要處理。
這裡假設綁定 socket 的網卡跟用來實際通訊的網卡是同一張。
結語
雖然 StackOverflow
網站可以輕鬆找到這種問題的解答,或者該說眾多的解答,例如這個:http://stackoverflow.com/questions/166506/finding-local-ip-addresses-using-pythons-stdlib
。 但您看有多少個答案!排第一的答案還不適用山姆鍋遇到的情況。
所以,簡單歸簡單,這個問題還是值得紀錄一下讓更多人容易找到答案。