golang UDP服务器的奇怪行为

时间:2013-10-29 12:20:08

标签: networking udp go

我在go中写了一个简单的UDP服务器。

当我go run udp.go时,它会打印我发送给它的所有包裹。但是当运行go run udp.go > out时,它会在客户端停止时停止将stdout传递给out文件。

客户端是发送10k请求的简单程序。所以在文件中我有大约50%的已发送包。当我再次运行客户端时,out文件再次增长,直到客户端脚本完成。

服务器代码:

package main

import (
  "net"

  "fmt"
)

func main() {
  addr, _ := net.ResolveUDPAddr("udp", ":2000")
  sock, _ := net.ListenUDP("udp", addr)

  i := 0
  for {
    i++
    buf := make([]byte, 1024)
    rlen, _, err := sock.ReadFromUDP(buf)
    if err != nil {
      fmt.Println(err)
    }
    fmt.Println(string(buf[0:rlen]))
    fmt.Println(i)
    //go handlePacket(buf, rlen)
  }
}

这是客户端代码:

package main

import (
  "net"

  "fmt"
)

func main() {

  num := 0
  for i := 0; i < 100; i++ {
    for j := 0; j < 100; j++ {
      num++
      con, _ := net.Dial("udp", "127.0.0.1:2000")
      fmt.Println(num)
      buf := []byte("bla bla bla I am the packet")
      _, err := con.Write(buf)
      if err != nil {
        fmt.Println(err)
      }
    }
  }
}

2 个答案:

答案 0 :(得分:12)

如您所料,由于UDP的性质,它似乎是 UDP数据包丢失。由于UDP是无连接的,因此客户端不关心服务器是否可用或准备好接收数据。因此,如果服务器正忙于处理,则无法处理下一个传入的数据报。您可以查看netstat -u(应包括UDP数据包丢失信息)。我遇到了同样的事情,服务器(接收方)无法跟上发送的数据包。

你可以尝试两件事(第二件事就是我的例子):

调用SetReadBuffer。确保接收套接字具有足够的缓冲来处理您抛出的所有内容。

sock, _ := net.ListenUDP("udp", addr)
sock.SetReadBuffer(1048576)

在go例程中执行所有数据包处理。尝试通过确保服务器在您希望其可用于接收时不忙于执行其他工作来尝试每秒增加数据报。即将处理工作移至go例程,因此不要保持ReadFromUDP()。

//Reintroduce your go handlePacket(buf, rlen) with a count param
func handlePacket(buf []byte, rlen int, count int)
        fmt.Println(string(buf[0:rlen]))
        fmt.Println(count)
}

...

go handlePacket(buf, rlen, i)

最后一个选项:

最后,可能不是你想要的,你在你的客户端安睡,这会降低速度并且也会消除问题。例如

buf := []byte("bla bla bla I am the packet")
time.Sleep(100 * time.Millisecond)
_, err := con.Write(buf)

答案 1 :(得分:1)

尝试在write语句后同步stdout。

os.Stdout.Sync()