import socket
import time
from zeroconf import ServiceInfo, Zeroconf
import os
# --- 配置区域 ---
TARGET_HOSTNAME = "gmobile.local."
# 服务名,用于局域网的服务列表显示
SERVICE_NAME = "Gmobile Discovery._http._tcp.local."
# 广播的端口。即使你不运行服务,mDNS也需要一个端口号。
TARGET_PORT = 80
# IP地址检查/重新广播间隔 (10 分钟)
CHECK_INTERVAL_SECONDS = 600
# --- 辅助函数 ---
def get_local_ip():
"""通过连接一个外部地址来获取本机在局域网的实际 IP 地址"""
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
# 尝试连接一个不路由的IP地址,迫使系统选择一个有效的本地IP
s.connect(('10.255.255.255', 1))
IP = s.getsockname()[0]
except Exception:
# 如果获取失败,则返回本地回环地址
IP = '127.0.0.1'
finally:
s.close()
return IP
def run_service_monitor():
"""主监控循环,每 10 分钟强制注销并重新注册 mDNS 服务"""
print(f"[*] mDNS 监控器已启动,目标域名: {TARGET_HOSTNAME}")
print(f"[*] 强制重新广播间隔: {CHECK_INTERVAL_SECONDS} 秒")
try:
while True:
# 1. 获取当前 IP
current_ip = get_local_ip()
# --- 强制重新注册逻辑 ---
# 2. 每次循环都创建新的 Zeroconf 实例和信息对象
zeroconf = None
info = None
print(f"\n[!!!] 正在进行强制重新注册,当前 IP:{current_ip}")
# 3. 注册新服务
try:
# 每次都创建新的 Zeroconf 实例
zeroconf = Zeroconf()
info = ServiceInfo(
"_http._tcp.local.",
SERVICE_NAME,
# 注意:socket.inet_aton() 必须在当前 IP 下运行
addresses=[socket.inet_aton(current_ip)],
port=TARGET_PORT,
server=TARGET_HOSTNAME, # 关键:指定单一主机名
properties={'desc': 'Gmobile Local Access'}
)
# 注册服务
zeroconf.register_service(info)
print(f"[SUCCESS] {TARGET_HOSTNAME} 已成功广播!")
# 保持服务活跃 CHECK_INTERVAL_SECONDS 秒
print(f"[*] 服务将保持活跃 {CHECK_INTERVAL_SECONDS} 秒,之后进行下一次强制更新。")
time.sleep(CHECK_INTERVAL_SECONDS)
except Exception as e:
print(f"[ERROR] 注册服务失败: {e}")
# 注册失败,等待 60 秒后重试
time.sleep(60)
finally:
# 4. 强制清理:注销服务并关闭 Zeroconf 实例
if zeroconf:
if info:
zeroconf.unregister_service(info)
zeroconf.close()
print("[*] 服务已强制注销,准备进行下一轮循环。")
except KeyboardInterrupt:
print("\n[*] 接收到停止信号,正在注销服务...")
except Exception as e:
print(f"\n[CRITICAL ERROR] 脚本异常中断: {e}")
finally:
# 5. 最终清理
if 'zeroconf' in locals() and zeroconf and zeroconf.is_running:
if info:
zeroconf.unregister_service(info)
zeroconf.close()
print("[*] 服务已安全退出。")
if __name__ == '__main__':
run_service_monitor()
发表回复