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

Golang UDP固定端口客户端重复请求报address already in use问题求助

问题描述

首次请求UDP服务器可正常运行,但第二次输入请求时触发如下错误:

panic: Listen failed:dial udp :8829->:9781: bind: address already in use

代码实现如下:

package main

import (
    "fmt"
    "log"
    "net"
    "os"
)

func main() {
    log.SetFlags(log.Lshortfile)
    udpServer, err := net.ResolveUDPAddr("udp", ":9781")

    if err != nil {
        panic(fmt.Sprint("ResolveUDPAddr failed:", err.Error()))
        os.Exit(1)
    }

    client, err := net.ResolveUDPAddr("udp", ":8829")
    if err != nil {
            panic(err)
    }

    for {
        fmt.Printf(">> ")

        var input string
        fmt.Scanf("%s", &input)

        conn, err := net.DialUDP("udp", client, udpServer)
        if err != nil {
            panic(fmt.Sprint("Listen failed:", err.Error()))
            os.Exit(1)
        }

        _, err = conn.Write([]byte(input))
        if err != nil {
            panic(fmt.Sprint("Write data failed:", err.Error()))
            os.Exit(1)
        }

        received := make([]byte, 1024)
        _, err = conn.Read(received)
        if err != nil {
            panic(fmt.Sprint("Read data failed:", err.Error()))
            os.Exit(1)
        }

        fmt.Printf("Response: %s\n", string(received))
    }

}

需求为使用固定客户端端口,无法通过将client设为nil使用随机端口解决,特此求助。


问题原因与解决方案

原因分析

每次循环调用net.DialUDP时,都会尝试绑定固定端口:8829,但第一次创建的UDP连接conn未被关闭,操作系统判定该端口仍被占用,导致第二次绑定失败。UDP虽为无连接协议,但DialUDP创建的连接会持续占用本地端口,直到连接被主动关闭。

解决方案

推荐复用UDP连接的方案,整个程序仅创建一次连接,循环内复用该连接完成收发操作,既满足固定端口需求,又避免端口重复绑定问题。修改后的代码如下:

package main

import (
    "fmt"
    "log"
    "net"
    "os"
)

func main() {
    log.SetFlags(log.Lshortfile)
    udpServer, err := net.ResolveUDPAddr("udp", ":9781")
    if err != nil {
        panic(fmt.Sprint("ResolveUDPAddr failed:", err.Error()))
        os.Exit(1)
    }

    client, err := net.ResolveUDPAddr("udp", ":8829")
    if err != nil {
        panic(err)
    }

    // 仅创建一次UDP连接,绑定固定端口
    conn, err := net.DialUDP("udp", client, udpServer)
    if err != nil {
        panic(fmt.Sprint("Listen failed:", err.Error()))
        os.Exit(1)
    }
    defer conn.Close() // 程序退出时自动关闭连接,释放端口

    for {
        fmt.Printf(">> ")

        var input string
        fmt.Scanf("%s", &input)

        _, err = conn.Write([]byte(input))
        if err != nil {
            panic(fmt.Sprint("Write data failed:", err.Error()))
            os.Exit(1)
        }

        received := make([]byte, 1024)
        _, err = conn.Read(received)
        if err != nil {
            panic(fmt.Sprint("Read data failed:", err.Error()))
            os.Exit(1)
        }

        fmt.Printf("Response: %s\n", string(received))
    }
}

关键说明

  • 将DialUDP移至循环外部,避免重复绑定同一端口。
  • 使用defer conn.Close()确保程序退出时正确释放端口资源。
  • UDP连接复用完全适配固定端口需求,同一连接可完成多次收发操作,不影响通信逻辑。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.11 05:25:04