[英]Python: Get local IP-Address used to send IP data to a specific remote IP-Address
我正在使用Python腳本將UDP數據包發送到服務器,該服務器將注冊我的腳本以接收來自服務器的通知。 該協議要求我發送自己的IP地址和端口,我希望收到這些通知,因此這應該是可以從服務器網絡訪問的地址。
解決方案至少應該適用於Windows XP及更高版本,最好是Mac OS X,因為這是我的開發平台。
第一步是獲取任何接口的IP地址。 我目前正在使用通常建議的解析機器自己的主機名的方法:
def get_local_address():
return socket.gethostbyname(socket.gethostname())
這有時只能起作用。 目前它返回172.16.249.1
,這是VM Ware使用的虛擬接口的地址,所以這是一個問題。
更好的方法是獲取默認接口的IP地址,這在大多數時候應該是正確的。
更好的方法是通過面向連接的協議(如TCP)獲取用於連接服務器的實際IP地址。 我實際上可以獲得該地址,但不是在沒有嘗試打開連接的情況下:
def get_address_to_connect_to(server_addr):
non_open_port = 50000
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
try:
s.connect((server_addr, non_open_port))
except socket.error:
pass
else:
s.close() # just in case
return s.getsockname()[0]
在服務器無法訪問或其間的惡意防火牆阻止ICMP數據包的情況下,這將阻止直到達到某個TCP超時。 有沒有更好的方法來獲取這些信息?
我不得不一次解決同樣的問題,並花了相當多的時間試圖找到一個更好的方法,但沒有成功。 我也開始使用gethostname,但是你發現它並不總是返回正確的結果,甚至可以在hosts文件出現問題的情況下拋出異常。
我能找到的唯一可以跨平台可靠運行的解決方案是嘗試連接,就像你正在做的那樣。 您的代碼的一個改進是使用UDP而不是TCP,即SOCK_DGRAM而不是SOCK_STREAM。 這避免了連接超時,並且該功能立即完成。
如果要將此代碼部署到可能正在運行防火牆的客戶端位置,請確保記錄它執行此檢查的事實。 否則,他們可能會看到針對端口50000的出站連接的防火牆警告,不了解其目的,並將其視為錯誤。
編輯:這里大致是我使用的代碼:
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
s.connect((host, 9))
client = s.getsockname()[0]
except socket.error:
client = "Unknown IP"
finally:
del s
return client
我認為你得到的是0.0.0.0,因為你在調用getsockname之前關閉套接字。 另一個提示是我使用端口9; 它是RFC863 UDP丟棄端口,因此比一些隨機高編號端口略微怪異。
發送方是否需要知道其IP地址?
在發送UDP'寄存器'之后,客戶端是否只能監聽其嘗試訂閱的數據(在所有接口上)並讓服務器開始將數據發送到數據報源自的地址?
聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.