我有一个简单的DPP服务器,它监听数据包,等待50毫秒以表现得好像正在进行操作,然后将消息打印到终端.这是服务器代码:
package main
import (
"fmt"
"log"
"log/slog"
"net"
"time"
)
func main() {
udpAddr, err := net.ResolveUDPAddr("udp", "0.0.0.0:8080")
if err != nil {
log.Fatal(err)
}
conn, err := net.ListenUDP("udp", udpAddr)
if err != nil {
log.Fatal(err)
}
slog.Info("UDP server listening", "addr", udpAddr, "workers", numCpu)
go startWorker(0, conn)
// Block forever
<-make(chan struct{})
}
func startWorker(id int, conn *net.UDPConn) {
slog.Info("Starting worker", "id", id)
i := 0
for {
buf := make([]byte, 1024)
_, _, err := conn.ReadFromUDP(buf)
if err != nil {
slog.Error("failed to read UDP message", "err", err, "worker", id)
continue
}
time.Sleep(50 * time.Millisecond)
fmt.Print(i, " > ", string(buf))
i += 1
}
}
我有一个go客户端代码,它只需向该服务器发送一次字符串消息.以下是客户端代码:
package main
import (
"log"
"net"
)
func main() {
udpAddr, err := net.ResolveUDPAddr("udp", "0.0.0.0:8080")
if err != nil {
log.Fatal(err)
}
conn, err := net.DialUDP("udp", nil, udpAddr)
if err != nil {
log.Fatal(err)
}
// Send a message to the server
_, err = conn.Write([]byte("Hello UDP Server\n"))
if err != nil {
log.Fatal(err)
}
}
我想测试服务器中可以处理多少个数据包.所以我所做的是,我顺序运行了10000次客户端代码,看看其中有多少代码会被处理.但每次只处理大约400-500个包.以下是我在终端上进行测试的方式:
time (for i in $(seq 10000); do ./client; done)
没有错误日志(log),输出是:
real 0m12,538s
user 0m10,667s
sys 0m4,014s
我认为由于操作系统缓冲区的限制,这可能是一个问题.所以我在服务器代码中添加了以下go startWorker(id, conn)
之前的代码:
// 1 GB
if err = conn.SetReadBuffer(1024 * 1024 * 1024); err != nil {
log.Fatal(err)
}
进行完全相同的测试后,已处理的数据包数量变为600-700.1 GB的缓冲区不可能不足以容纳10000个这个简单的"Hello DPP服务器\n"消息.有人能向我解释一下这种行为背后的原因以及我如何解决它吗?
P.S.:我正在使用Ubuntu 22.04