You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

Go语言UDP本地请求出现约5%丢包问题求助

本地UDP高丢包问题排查求助

服务端代码(server.go)

package main

//server.go

import (
    "fmt"
    "net"
    "os"
    "os/signal"
    "syscall"
)

func main() {
    tcp := 0
    udp := 0

    defer func(o, t *int) {
        fmt.Println(*o, *t)
    }(&tcp, &udp)

    go func() {
        l, err := net.ListenTCP("tcp", &net.TCPAddr{
            IP:   net.ParseIP("0.0.0.0"),
            Port: 3000,
        })
        if err != nil {
            panic(err)
        }

        b := make([]byte, 24)

        for {
            conn, err := l.Accept()
            if err != nil {
                continue
            }

            n, err := conn.Read(b)
            if err != nil {
                continue
            }

            r := string(b[:n])

            if r == "close" {
                conn.Close()
                break
            } else {
                _, err = conn.Write([]byte("pong"))
                if err != nil {
                    continue
                }
            }

            conn.Close()
            tcp++
        }

        l.Close()
    }()

    go func() {
        conn, err := net.ListenUDP("udp", &net.UDPAddr{
            IP:   net.ParseIP("0.0.0.0"),
            Port: 3000,
        })
        if err != nil {
            panic(err)
        }

        b := make([]byte, 24)

        for {
            n, addr, err := conn.ReadFromUDP(b)
            if err != nil {
                continue
            }

            r := string(b[:n])

            if r == "close" {
                break
            } else {
                _, err = conn.WriteToUDP([]byte("pong"), addr)
                if err != nil {
                    continue
                }
            }

            udp++
        }

        conn.Close()
    }()

    signals := make(chan os.Signal, 1)
    signal.Notify(signals, os.Interrupt, syscall.SIGTERM)

    <-signals
}

客户端代码(client.go)

package main

//client.go

import (
    "fmt"
    "net"
    "os"
    "os/signal"
    "strconv"
    "sync/atomic"
    "syscall"
    "time"
)

func main() {
    t := "tcp"
    m := "ping"

    c := 1

    if len(os.Args) > 1 {
        t = os.Args[1]
    }

    if len(os.Args) > 2 {
        m = os.Args[2]
    }

    if len(os.Args) > 3 {
        c, _ = strconv.Atoi(os.Args[3])
    }

    tcp := int64(0)
    udp := int64(0)

    defer func(o, t *int64) {
        fmt.Println(*o, *t)
    }(&tcp, &udp)

    if c == 1 {
        if t == "tcp" {
            addr, err := net.ResolveTCPAddr("tcp", ":3000")
            if err != nil {
                panic(err)
            }

            conn, err := net.DialTCP("tcp", nil, addr)
            if err != nil {
                panic(err)
            }

            _, err = conn.Write([]byte(m))
            if err != nil {
                panic(err)
            }

            tcp++
        }

        if t == "udp" {
            addr, err := net.ResolveUDPAddr("udp", ":3000")
            if err != nil {
                panic(err)
            }

            conn, err := net.DialUDP("udp", nil, addr)
            if err != nil {
                panic(err)
            }

            _, err = conn.Write([]byte(m))
            if err != nil {
                panic(err)
            }

            udp++
        }

        os.Exit(0)
    }

    for i := 0; i < c; i++ {
        go func() {
            a1, err := net.ResolveTCPAddr("tcp", ":3000")
            if err != nil {
                panic(err)
            }
            c1, err := net.DialTCP("tcp", nil, a1)
            if err != nil {
                panic(err)
            }

            _, err = c1.Write([]byte(m))
            if err != nil {
                panic(err)
            }

            buf := make([]byte, 24)

            n, err := c1.Read(buf)
            if err != nil {
                panic(err)
            }

            if string(buf[:n]) != "pong" {
                panic(1)
            }

            err = c1.Close()
            if err != nil {
                panic(err)
            }

            g := atomic.AddInt64(&tcp, 1)

            if g % 100 == 0 {
                fmt.Println("tcp", g)

                time.Sleep(time.Millisecond * 1000)
            }
        }()

        go func() {
            a2, err := net.ResolveUDPAddr("udp", ":3000")
            if err != nil {
                panic(err)
            }
            c2, err := net.DialUDP("udp", nil, a2)
            if err != nil {
                panic(err)
            }

            _, err = c2.Write([]byte(m))
            if err != nil {
                panic(err)
            }

            buf := make([]byte, 24)

            n, err := c2.Read(buf)
            if err != nil {
                panic(err)
            }

            if string(buf[:n]) != "pong" {
                panic(1)
            }

            err = c2.Close()
            if err != nil {
                panic(err)
            }

            g := atomic.AddInt64(&udp, 1)

            if g % 100 == 0 {
                fmt.Println("udp", g)

                time.Sleep(time.Millisecond * 1000)
            }
        }()
    }


    signals := make(chan os.Signal, 1)
    signal.Notify(signals, os.Interrupt, syscall.SIGTERM)

    <-signals
}

问题现象

发送100或200个请求时,服务端与客户端均显示所有UDP请求正常处理;但发送1000个请求时,UDP请求出现约5%的丢包,且无panic抛出。虽然UDP本身允许丢包,但本地localhost环境下该丢包率过高,怀疑存在代码或逻辑问题,寻求排查帮助。

内容的提问来源于stack exchange,提问作者Gohryt

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.15 16:31:01