package main import ( "encoding/json" "flag" "fmt" "net" "os" "os/exec" "runtime" "strings" "time" ) type BroadcastMessage struct { Type string `json:"type"` IP string `json:"ip"` Port int `json:"port"` Name string `json:"name"` } func getGatewayIP() (string, error) { var cmd *exec.Cmd if runtime.GOOS == "linux" { cmd = exec.Command("sh", "-c", "ip route | grep default | awk '{print $3}'") } else if runtime.GOOS == "darwin" { cmd = exec.Command("sh", "-c", "netstat -rn | grep default | awk '{print $2}'") } else { return "", fmt.Errorf("unsupported OS") } out, err := cmd.Output() if err != nil { return "", err } return strings.TrimSpace(string(out)), nil } func ipInSameSubnet(ip1 net.IP, ip2 net.IP, mask net.IPMask) bool { if mask == nil { return false } net1 := ip1.Mask(mask) net2 := ip2.Mask(mask) return net1.Equal(net2) } func getLocalIP() string { gatewayStr, err := getGatewayIP() if err != nil { fmt.Println("Failed to get gateway IP:", err) return "127.0.0.1" } gateway := net.ParseIP(gatewayStr) if gateway == nil { fmt.Println("Invalid gateway IP") return "127.0.0.1" } interfaces, err := net.Interfaces() if err != nil { fmt.Println("Failed to get network interfaces:", err) return "127.0.0.1" } for _, iface := range interfaces { if iface.Flags&net.FlagUp == 0 { continue // interface down } addrs, err := iface.Addrs() if err != nil { continue } for _, addr := range addrs { var ip net.IP var mask net.IPMask switch v := addr.(type) { case *net.IPNet: ip = v.IP mask = v.Mask case *net.IPAddr: ip = v.IP } if ip == nil || ip.IsLoopback() || ip.To4() == nil { continue } if ipInSameSubnet(ip, gateway, mask) { return ip.String() } } } return "127.0.0.1" } func main() { // 参数 var ( port = flag.Int("port", 8000, "Device service port") interval = flag.Int("interval", 2, "Broadcast interval in seconds") name = flag.String("name", "My-AI-Server", "Device name") ) flag.Parse() ip := getLocalIP() if ip == "127.0.0.1" { fmt.Println("Warning: failed to find suitable IP address, using loopback") } addr := net.UDPAddr{ IP: net.IPv4bcast, Port: 9876, } conn, err := net.DialUDP("udp4", nil, &addr) if err != nil { fmt.Println("Failed to dial UDP broadcast:", err) os.Exit(1) } defer conn.Close() for { msg := BroadcastMessage{ Type: "ai_server_announce", IP: ip, Port: *port, Name: *name, } data, _ := json.Marshal(msg) _, err := conn.Write(data) if err != nil { fmt.Println("Broadcast failed:", err) } else { fmt.Printf("Broadcasted: %s:%d (%s)\n", ip, *port, *name) } time.Sleep(time.Duration(*interval) * time.Second) } }