• 首页 首页 icon
  • 工具库 工具库 icon
    • IP查询 IP查询 icon
  • 内容库 内容库 icon
    • 快讯库 快讯库 icon
    • 精品库 精品库 icon
    • 问答库 问答库 icon
  • 更多 更多 icon
    • 服务条款 服务条款 icon

golang udp 连接在所有其他写入时被拒绝

用户头像
it1352
帮助1

问题说明

我在 ubuntu linux 16.04 上运行了这个 UDP 客户端程序:

I ran this UDP client program on ubuntu linux 16.04:

package main

import (
    "fmt"
    "net"
    "time"
    "strconv"
)

func CheckError(err error) {
    if err  != nil {
        fmt.Println("Error: " , err)
    }
}

func main() {
    ServerAddr,err := net.ResolveUDPAddr("udp","127.0.0.1:10001")
    CheckError(err)

    LocalAddr, err := net.ResolveUDPAddr("udp", "127.0.0.1:0")
    CheckError(err)

    Conn, err := net.DialUDP("udp", LocalAddr, ServerAddr)
    CheckError(err)

    defer Conn.Close()
    i := 0
    for {
        msg := strconv.Itoa(i)
        i  
        buf := []byte(msg)
        _,err := Conn.Write(buf)
        if err != nil {
            fmt.Println(msg, err)
        }
        time.Sleep(time.Second * 1)
    }
}

它产生这个输出:

$ go run server.go 
1 write udp 127.0.0.1:58703->127.0.0.1:10001: write: connection refused
3 write udp 127.0.0.1:58703->127.0.0.1:10001: write: connection refused
5 write udp 127.0.0.1:58703->127.0.0.1:10001: write: connection refused

但我希望得到这个输出:

But I expected this output instead:

$ go run server.go 
1 write udp 127.0.0.1:58703->127.0.0.1:10001: write: connection refused
2 write udp 127.0.0.1:58703->127.0.0.1:10001: write: connection refused
3 write udp 127.0.0.1:58703->127.0.0.1:10001: write: connection refused
4 write udp 127.0.0.1:58703->127.0.0.1:10001: write: connection refused
5 write udp 127.0.0.1:58703->127.0.0.1:10001: write: connection refused

tcpdump 说:

15:28:46.453313 IP localhost.47993 > localhost.10001: UDP, length 1
15:28:46.453338 IP localhost > localhost: ICMP localhost udp port 10001 unreachable, length 37
15:28:48.453821 IP localhost.47993 > localhost.10001: UDP, length 1
15:28:48.453852 IP localhost > localhost: ICMP localhost udp port 10001 unreachable, length 37
15:28:50.454242 IP localhost.47993 > localhost.10001: UDP, length 1
15:28:50.454271 IP localhost > localhost: ICMP localhost udp port 10001 unreachable, length 37

为什么每隔一次 conn.Write 写入而不是每次都会发生这种情况?我不是在责怪go,我只是想知道为什么.

Why does this happen every other time conn.Write writes instead of every time? I'm not blaming go, I just want to learn why.

正确答案

#1

如果您更仔细地查看数据包捕获,您会注意到它回复每个 ICMP 无法访问的数据包,而您只是发送每隔一个数据包.如果您检查 Write 的返回值,您还会看到没有数据写入其他每个数据包.

If you look more closely at the packet capture, you'll notice that it is replying to every packet with an ICMP unreachable, and you are only sending every other packet. If you inspect the return value from Write, you'll also see that no data was written on every other packet.

因为 UDP 没有真正的连接并且发送的任何数据包都没有 ACK,所以已连接"的 UDP 套接字可以用来模拟发送失败的最佳方法是保存 ICMP 响应,并在下一次将其作为错误返回写.

Because UDP has no real connection and there is no ACK for any packets sent, the best a "connected" UDP socket can do to simulate a send failure is to save the ICMP response, and return it as an error on the next write.

所以第一个包发送,收到一个ICMP不可达报文,第二个发送操作失败返回错误,所以没有包发送,循环往复.

So the first packet is sent, an ICMP unreachable message is received, the second send operation fails and returns the error, so no packet is sent, and the cycle repeats.

这篇好文章是转载于:学新通技术网

  • 版权申明: 本站部分内容来自互联网,仅供学习及演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,请提供相关证据及您的身份证明,我们将在收到邮件后48小时内删除。
  • 本站站名: 学新通技术网
  • 本文地址: /reply/detail/tanhcfhijj
系列文章
更多 icon
同类精品
更多 icon
继续加载