2017-10-11 47 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不可達消息,第二個發送操作失敗並返回錯誤,因此不發送數據包,並且重複該循環。