我有一个简单的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

推荐答案

try 增加操作系统上的DPP缓冲区的大小.您可以根据您的操作系统使用这些命令:

Linux:

sudo sysctl -w net.core.rmem_max=...

MacOS:

sudo sysctl -w net.inet.udp.recvspace=...

Windows:
On Windows, you can adjust the UDP buffer size by modifying the registry. The relevant key is HKEY_LOCAL_MACHINE\SYSTEM\CurrentControlSet\Services\Afd\Parameters\DefaultReceiveWindow.

Go相关问答推荐

如何将泛型函数作为参数传递给golang中的另一个函数?

如何在使用中介资源时处理函数中的`defer`

GORM没有从 struct 创建完整的表,如何修复?

../golang/pkg/mod/github.com/wmentor/lemmas@v0.0.6/processor.go:72:9:未定义:令牌.进程

在Uber FX中实现后台进程正常关闭的正确方式是什么?

Golang中的泛型 struct /接口列表

Go中的Slice[:1][0]与Slice[0]

如何解析Go-Gin多部分请求中的 struct 切片

关于如何使用 Service Weaver 设置多个不同侦听器的问题

在 Windows 11 上运行 go mod tidy 时的 gitlab 权限问题

我如何使用 TOML fixtures 在使用 Go Buffalo 框架的开发环境中为我的数据库 seeder ?

整理时转换值

grpc-gateway:重定向与定义不匹配(原始文件)

使用 GO 在侧 tar 文件中提取 tar 文件的最快方法

如何在 helm 中将字符串连接到 .AsConfig 的结果?

如何在测试中使用自定义标志(使用`testify/suite`)

如何在 GORM 中迭代一个 int 数组

如何 Select 前 N 个元素 Gin-Gorm

Golang SSH客户端错误无法验证,try 的方法[无公钥],没有支持的方法

Gin中测试模式有什么用