Golang UDP服务器的奇怪行为

I wrote a simple UDP server in go.

When I do go run udp.go it prints all packages I send to it. But when running go run udp.go > out it stops passing stdout to the out file when the client stops.

The client is simple program that sends 10k requests. So in the file I have around 50% of sent packages. When I run the client again, the out file grows again until the client script finishes.

Server code:

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)
  }
}

And here is the client code:

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)
      }
    }
  }
}
doutangkao2789
doutangkao2789 我添加了错误检查,没有任何此类问题。客户端正常工作,我在另一台服务器上对其进行了测试。似乎重定向使套接字读取时滞,并且丢失了一些数据包。
接近 7 年之前 回复
dpba63888
dpba63888 您将忽略客户端和服务器中的几种可能的错误。运行客户端时,它立即引发运行时错误。添加错误检查后:“拨号udp127.0.0.1:2000:打开的文件太多”。如果不知道您的问题是否相关,但是我想请您添加检查所有可能的错误的方法,如果那不能为您解决问题,请返回结果:)
接近 7 年之前 回复

2个回答



您怀疑,由于UDP的性质,看来 UDP数据包丢失</ strong>。 由于UDP是无连接的,因此客户端不关心服务器是否可用或准备接收数据。 因此,如果服务器忙于处理,它将无法处理下一个传入的数据报。 您可以使用 netstat -u </ code>(应该包含UDP数据包丢失信息)进行检查。 我遇到了同样的事情,服务器(接收端)无法跟上发送的数据包。</ p>

您可以尝试两种方法(第二种方法对我的示例有用) :</ p>

调用SetReadBuffer。</ strong>确保接收套接字具有足够的缓冲以处理您向其抛出的所有内容。</ p>

 袜子,_:= net.ListenUDP(“ udp”,addr)
sock.SetReadBuffer(1048576)
</ code> </ pre>

一次执行所有数据包处理 </ strong>。尝试通过确保服务器在可以接收时不忙于其他工作来每秒增加数据报的数量。 即,将处理工作移至go例程,因此您无需按住ReadFromUDP()。 </ p>

  //重新引入带有计数参数的go handlePacket(buf,rlen)
func handlePacket(buf [] byte,rlen int,count int)
fmt.Println( 字符串(buf [0:rlen]))
fmt.Println(count)
}
</ code> </ pre>

... </ p>

< pre> go handlePacket(buf,rlen,i)
</ code> </ pre>

最后一个选项:</ em> </ p>

最后,也许不是您想要的,您让您的客户入睡</ strong>,这会减慢速度并消除问题。 例如 </ p>

  buf:= [] byte(“ bla bla bla我是数据包”)
time.Sleep(100 * time.Millisecond)
_,err:= con。 写(buf)
</ code> </ pre>
</ div>

展开原文

原文

As you suspected, it seems like UDP packet loss due to the nature of UDP. Because UDP is connectionless, the client doesn't care if the server is available or ready to receive data. So if the server is busy processing, it won't be available to handle the next incoming datagram. You can check with netstat -u (which should include UDP packet loss info). I ran into the same thing, in which the server (receive side) could not keep up with the packets sent.

You can try two things (the second worked for me with your example):

Call SetReadBuffer. Ensure the receive socket has enough buffering to handle everything you throw at it.

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

Do all packet processing in a go routine. Try to increase the datagrams per second by ensuring the server isn't busy doing other work when you want it to be available to receive. i.e. Move the processing work to a go routine, so you don't hold up 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)

One final option:

Lastly, and probably not what you want, you put a sleep in your client which would slow down the rate and would also remove the problem. e.g.

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

dougang8233
dougang8233 附带一提,ReadFromUDP可以在go例程中完成,这有时可以简化处理并节省通道。
5 年多之前 回复



尝试在write语句之后同步标准输出。 </ p>

  os.Stdout.Sync()
</ code> </ pre>
</ div>

展开原文

原文

Try syncing stdout after the write statements.

os.Stdout.Sync() 

duan_2000
duan_2000 “当它指向一个终端时”,起作用的情况就是那个,而一个不起作用的情况正是。 由于服务器永不退出,因此Stdout不会在退出时被刷新。
接近 7 年之前 回复
doufeng2877
doufeng2877 我不认为这是问题。 IMO stdout在收到的每个换行符上都会刷新,或者应用程序通常使用exit退出。 请参见手册页。 “流stdout指向终端时是行缓冲的。只有在调用fflush(3)或exit(3)或打印换行符时,才会出现部分行。”
接近 7 年之前 回复
Csdn user default icon
上传中...
上传图片
插入图片
抄袭、复制答案,以达到刷声望分或其他目的的行为,在CSDN问答是严格禁止的,一经发现立刻封号。是时候展现真正的技术了!
立即提问
相关内容推荐