Golang微控制器环境下,仅用net包通过UDP函数发送HTTP请求可行吗?
不用net/http包,纯UDP实现SSDP M-SEARCH请求
核心结论
完全可以不依赖net/http包,直接手动构造符合HTTP格式的字节切片,通过net包的UDP函数(DialUDP/ListenUDP/WriteToUDP等)发送SSDP发现请求,也能正常接收设备响应。SSDP本质是基于UDP的HTTPU协议,只要遵循HTTP请求的格式规范即可,不需要net/http的序列化逻辑。
手动构造SSDP请求的方法
SSDP的M-SEARCH请求是标准的HTTP格式,结构如下(注意每行结尾必须是\r\n,最后要追加一个空行,即连续两个\r\n):
M-SEARCH * HTTP/1.1 HOST: 239.255.255.250:1900 MAN: "ssdp:discover" MX: 3 ST: ssdp:all
你可以直接将这个格式拼接成字符串,再转换为[]byte,就得到了可通过UDP发送的请求数据。
TinyGo + net包实现示例
以下是纯net包的实现代码,适配TinyGo环境:
package main import ( "log" "net" "time" ) const ( ssdpUDP4Addr = "239.255.255.250:1900" ssdpSearchString = "M-SEARCH * HTTP/1.1\r\nHOST: 239.255.255.250:1900\r\nMAN: \"ssdp:discover\"\r\nMX: 3\r\nST: ssdp:all\r\n\r\n" ) func main() { // 创建UDP连接 conn, err := net.DialUDP("udp", nil, &net.UDPAddr{IP: net.ParseIP("239.255.255.250"), Port: 1900}) if err != nil { log.Fatalf("Failed to dial UDP: %v", err) } defer conn.Close() // 设置读取超时,避免无限等待 err = conn.SetReadDeadline(time.Now().Add(5 * time.Second)) if err != nil { log.Fatalf("Failed to set read deadline: %v", err) } // 发送SSDP请求 _, err = conn.Write([]byte(ssdpSearchString)) if err != nil { log.Fatalf("Failed to send SSDP request: %v", err) } // 接收设备响应 buf := make([]byte, 2048) for { n, addr, err := conn.ReadFromUDP(buf) if err != nil { // 超时退出循环 if netErr, ok := err.(net.Error); ok && netErr.Timeout() { log.Println("Read timeout, no more responses") break } log.Fatalf("Failed to read UDP response: %v", err) } log.Printf("Received from %s:\n%s", addr, string(buf[:n])) } }
关键说明
- 手动构造的请求字符串严格遵循HTTP/1.1规范,
MAN字段的引号要保留,MX表示设备响应的最大延迟(秒),ST指定搜索目标(这里是所有SSDP设备)。 - 由于是UDP广播,可能会收到多个设备的响应,所以需要循环读取直到超时。
- 相比
net/http包,这种方式完全不依赖HTTP相关的结构体和序列化逻辑,更适合TinyGo这类对标准库支持有限的环境,减少了不必要的依赖。
内容的提问来源于stack exchange,提问作者Abram
相关产品推荐
相关产品推荐

