1

我正在尝试实现以下 UDP 协议,但我在弄清楚我应该如何处理这个问题时遇到了一些麻烦。

该协议规定我应该将特定的 UDP 数据包发送到某个服务器,之后服务器将流式传输(几个相关的 UDP 数据包)向我返回响应,也作为 UDP 数据包。我已经成功地使用以下代码发送了 UDP 数据包:

connection, error := net.DialUDP("udp", nil, endpoint)
...
if written, error := connection.Write(query.ToBytes()); error != nil {
    ...
} else {
    log.Printf("Successfully wrote %d bytes to %s", written, connection.RemoteAddr())
}

当我使用 Wireshark 并查看线路上发生了什么时,它看起来好像发送数据包很好(这里唯一的问题是我从来没有得到服务器的回复,但这与这个问题无关)。

在这种情况下,我处理服务器回复的最佳方式是什么?我可以使用先前建立connection的来读取服务器响应(这对我来说似乎不太可能,因为它是 UDP 无连接)还是应该使用net.ListenUDP(...)在正确的本地地址和端口上建立服务器来读取服务器发回给我的任何内容?

4

2 回答 2

1

该协议的意图显然是您只需使用相同的 UDP 套接字来接收您用来发送请求的回复。如果您有客户端防火墙,则必须在发送之前显式打开 UDP 端口并将 UDP 套接字绑定到该端口。否则只是让系统选择本地端口,根本不绑定。

短语“与初始数据包建立的端口相同”具有误导性。它们是你的话,还是协议规范的?当您进行第一次发送时真正发生的是,如果您还没有绑定套接字,它会自动绑定到系统选择的端口,就像您将它绑定到端口 0 一样。

于 2012-09-16T09:41:32.120 回答
0

由于特定的协议设计,不可能知道服务器将在哪个端口发送其回复数据包。在再次查看数据包转储后,我注意到服务器实际上确实回复了,只有客户端立即回复了一条 ICMP 消息说Destination port unreachable。所以服务器试图回复,但它不能,因为客户端不会接受该端口上的数据包。

为了解决这个问题,我曾经net.ListenUDP在客户端使用已建立的连接的本地地址发送初始数据包后立即侦听传入的数据包:

incomingConnection, _ := net.ListenUDP("udp", connection.LocalAddr().(*net.UDPAddr))
log.Printf("Listening for packets on %s", incomingConnection.LocalAddr())
defer incomingConnection.Close()

之后incomingConnection可以用作Reader- 例如 - 读取服务器正在发送的数据包。

于 2012-09-16T08:24:30.320 回答