我有 C 语言背景,根据我的理解,UDP 是一种无连接协议(protocol),我认为这意味着如果不先建立连接就无法发送数据包。然而,当我进入 Go 并开始编写网络代码时。我意识到 Go 的 UDP 编写器在向主机发送数据包之前先调用主机。这是为什么?
最佳答案
UDP 是无连接的,至少在原则上是这样(实现各不相同)。但是还有一个实现细节需要担心:要从“我”(我的 IP 主机和端口地址)向“你”(你的 IP 主机和端口地址)发送一个 UDP 数据包(数据报),我必须至少,指定您的 IP 和端口。如果您想向我发送数据报,则情况相反。
根据底层操作系统,您或我可能能够通过sendto
系统调用来完成此操作。也就是说,我们从 socket
系统调用开始,然后使用 sendto
系统调用进行即发即弃:数据报发送或不发送,然后我们永远不要费心去看看接下来会发生什么。 sendto
调用采用目标地址,对于 TCP 或 UDP,该地址提供 IP 地址和端口。
或者,我们可以使用 socket
系统调用,然后是可选的 bind
系统调用,然后是 connect
系统调用。< sup>1 如果我们这样做,bind
会建立我们的本地端口(可能还有 IP 地址,如果我们有多个)并且 connect
会建立我们的目标 IP 地址和端口。现在我们可以使用 write
或 send
系统调用发送数据包。
(一些系统添加了 sendmsg
和其他类似的调用,它们通常是上述所有调用的超集,因此可以在没有初步 connect
的情况下使用。但是 所有 支持 TCP 的系统都有创建网络连接和绑定(bind)和或连接然后写入数据的概念。)
一个非常有用的最小公分母设置是假设您将在要创建网络连接时指定您的远程对等地址。要在 Go 中执行此操作,请使用 Dial
。即使您的底层系统只有原始 IP 套接字,该库也可以在这些套接字之上构建 UDP 并提供 Dial
接口(interface),然后它仍然可以在 Go 中工作。
1理想情况下,这可能应该是一个“建立对等信息”系统调用,提供本地和远程寻址信息,以及任何可选的标志。省略远程说明符将意味着“监听来自所有人的所有传入连接”。这将消除对 SO_REUSEADDR
标志的需要,该标志的存在只是因为无法区分 connect
之前的 bind
,或 listen
之前的 bind
。但是现在修复 4.2BSD 有点晚了。 😀
关于sockets - 为什么 UDP 编写器要拨号?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/59059874/