golang udp 连接在所有其他写入时被拒绝 [英] golang udp connection refused on every other write

查看:18
本文介绍了golang udp 连接在所有其他写入时被拒绝的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我在 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.

推荐答案

如果您更仔细地查看数据包捕获,您会注意到它回复每个 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.

这篇关于golang udp 连接在所有其他写入时被拒绝的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆