我正在使用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超时时间被触发。是否有更好的方法获取这些信息?
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]
。如果您能将您的代码添加到您的答案中,那就太好了! - Feuermurmelwith
语句替换了del s
。 - Feuermurmel