golang udp连接拒绝其他所有写

时间:2017-10-11 21:24:39

标签: linux go udp

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

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

但我期待这个输出:

$ 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写入而不是每次都写?我不会责怪去,我只是想了解原因。

2 个答案:

答案 0 :(得分:5)

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

因为UDP没有真正的连接,并且对于发送的任何数据包都没有ACK,所以最好的"连接" UDP套接字可以模拟发送失败是为了保存ICMP响应,并在下次写入时将其作为错误返回。

因此发送第一个数据包,收到ICMP不可达消息,第二个发送操作失败并返回错误,因此不发送数据包,循环重复。

答案 1 :(得分:0)

尝试

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

LocalAddr, err := net.ResolveUDPAddr("udp", "<ip address of outgoing interface>:0")

这应该有效