讨论一个 UDP 问题,关于监听。

151 天前
 gesse

服务器有多个 IP ,UDP 监听 0.0.0.0:1234 ,并接收 UDP 数据。 如果客户端通过其中一个 IP 和 1234 端口向服务器发送了 UDP 数据,怎么获取这个客户端连接的是服务器端那个 IP ?

C 语言我知道是可以用 IP_PKTINFO 套接字选项来实现的。

golang 不是很熟悉,有类似的实现吗?

2239 次点击
所在节点    程序员
10 条回复
kuanat
151 天前
如果是 connected 可以通过 UDPConn.LocalAddr() 获得,如果是 unconnected 要通过 ReadMsgUDP 的 oob 信息获取,底层实现应该还是 IP_PKTINFO 。

如果嫌麻烦可以每个 ip 对应一个实例或者 goroutine ,这样就知道本地绑定的 ip 了。
povsister
151 天前
拿四层的 IP 头,看 DST IP
go 的 socket 库是有函数可以顺带拿到 IP 头的
laminux29
151 天前
GeekGao
151 天前
```
package main

import (
"fmt"
"net"
)

func main() {
addr := "0.0.0.0:1234"
conn, err := net.ListenPacket("udp", addr)
if err != nil {
fmt.Println("ListenPacket:", err)
return
}
defer conn.Close()

buf := make([]byte, 1024)
for {
n, addr, err := conn.ReadFrom(buf)
if err != nil {
fmt.Println("ReadFrom:", err)
continue
}
fmt.Println("Received:", string(buf[:n]), "from", addr)
}
}
```
zhs227
151 天前
最近刚好在处理一个与这个有关的问题,楼主需要的是 udp 连接中 server 端的 IP (由于多 IP 监听导致的,即 ADDR_ANY ),不是需要客户端的 IP 与端口。
在 deepseek 中找了个答案好像能用(用 gpt-o 试了得到的答案无法运行),性能不太清楚怎么样。

```
package main

import (
"fmt"
"net"
"golang.org/x/net/ipv4"
)

func main() {
addr, err := net.ResolveUDPAddr("udp", "0.0.0.0:1234")
if err != nil {
fmt.Println("Error resolving UDP address:", err)
return
}

conn, err := net.ListenUDP("udp", addr)
if err != nil {
fmt.Println("Error listening on UDP:", err)
return
}
defer conn.Close()

pconn := ipv4.NewPacketConn(conn)
if err := pconn.SetControlMessage(ipv4.FlagDst, true); err != nil {
fmt.Println("Error setting control message:", err)
return
}

buffer := make([]byte, 1024)
for {
n, cm, src, err := pconn.ReadFrom(buffer)
if err != nil {
fmt.Println("Error reading from UDP:", err)
continue
}

if cm != nil && cm.Dst != nil {
fmt.Printf("Received %d bytes from %s to %s\n", n, src, cm.Dst)
} else {
fmt.Printf("Received %d bytes from %s\n", n, src)
}
}
}
```
zhs227
151 天前
虽是 AI 生成的,但我实际运行进行了验证是可用的。

# ./udp
Received 6 bytes from 192.168.1.109:53900 to 192.168.1.60
^C
gesse
150 天前
ipv4.NewPacketConn(conn).SetControlMessage(ipv4.FlagDst, true)

是可以的
bowser1701
150 天前
@gesse `net.UDPConn` 有 `ReadMsgUDP` 可以读到
lysShub
150 天前
@gesse

是用的域名吗?

client 用 DialUDP 连 Server ,RemoteAddr() 就是服务器 IP
lysShub
150 天前
楼上的什么 raw socket 都来,不至于

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/1052869

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX