我正在使用Python腳本向服務器發送UDP數據包,該服務器將註冊我的腳本以接收來自服務器的通知。該協議要求我發送我自己的IP地址和端口,我希望接收這些通知,因此這應該是從服務器網絡可以訪問的地址。Python:獲取用於將IP數據發送到特定遠程IP地址的本地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]
這將阻塞,直到有TCP超時在服務器無法訪問或與一個邪惡的防火牆封鎖ICMP的情況下已經達到數據包。有沒有更好的方法來獲取這些信息?
啊,甜蜜的同理心!使用'SOCK_DGRAM',它將近乎完美!但's.getsockname()'返回'('0.0.0.0',51770)'在我的情況下。我試過's = socket.socket(socket.AF_INET,socket.SOCK_DGRAM); s.sendto(b'hello',('1.2.3.4',50000)); s.getsockname()[0]'。如果你將你的代碼添加到你的答案中,那會很棒! – Feuermurmel
查看我編輯的答案。 – DNS
完美的作品;它甚至使用我不知道的[Discard Protocol](http://en.wikipedia.org/wiki/Discard_Protocol)!我用'with'語句取代了'del s'。 – Feuermurmel