2017-10-11 190 views
0

我跑在Ubuntu Linux 16.04这个UDP客户端程序:golang 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写入而不是每次?我不是在指责,我只是想知道为什么。

+0

你能分享你的服务器如何处理连接?看起来像被阻止或类似的东西 –

+0

除非你有一个要求,通常建议避免使用连接的UDP套接字。 – JimB

+0

@JimB这是什么“连接的UDP套接字”我认为UDP是无连接的?他们通常建议避免它在哪里? – selden

回答

4

如果在数据包捕获更仔细一看,你会发现它回复与ICMP不可达每一个数据包,而你只发送所有其他数据包。如果您检查Write的返回值,您还会看到没有数据写入每个其他数据包。

因为UDP没有真正的连接,并且没有发送任何数据包的ACK,所以最好的一个“连接的”UDP套接字可以用来模拟发送失败,就是保存ICMP响应,并将其作为错误返回给接下来写。

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