首页 > 解决方案 > 去 udp 连接拨号一次,然后发送很多

问题描述

请考虑下面的代码,它是服务的简化版本。我发起一个不。goroutines 在其生命周期中根据需要,并且当他们开始做事时,他们需要将 udp 消息发送到设定的目的地。

package main

import (
        "fmt"
        "log"
        "net"
        "time"
)

const (
        udp_dest = "192.168.1.200:514"
)

func main() {
        fmt.Println("Hello")
        message := "this is a test"
        log_message(&message)
        go worker(1)
        go worker(2)
        go worker(3)
        go worker(4)
        time.Sleep(3009 * time.Second)
}

func log_message(message *string) {
        RemoteAddr, err := net.ResolveUDPAddr("udp", udp_dest)
        if err != nil {
                //fmt.Println("Err,  net.ResolveUDPAddr", err)
                return
        }
        conn, err := net.DialUDP("udp", nil, RemoteAddr)
        if err != nil {
                return
        }
        udp_message := fmt.Sprintf("<30> %s", *message)
        Bytes, _ := conn.Write([]byte(udp_message))
        log.Printf("Sent %d Bytes to %s\n", Bytes, udp_dest)
}

func worker(tag int) {
        i := 0
        for {
                worker_message := fmt.Sprintf("Some message from worker%d, loop: %d", tag, i)
                log_message(&worker_message)
                // do some work..
                time.Sleep(300 * time.Second)
                i += 1
        }
}

在 mylog_message中,每次它被调用时,我们都在调用net.DialUDP它,我觉得这很浪费。我尝试尝试使用全局变量&net.UDPConn等,但无法开始工作。

请展示如何实现/优化这一点?只有一个 UDP 目的地,我希望守护进程Dial在其启动时执行一次,然后Write根据需要执行一次。

谢谢!


这是我到目前为止得到的:

package main

import (
        "fmt"
        "log"
        "net"
        "time"
)

const (
        udp_dest = "192.168.1.200:514"
)

var (
        myconn *net.UDPConn
)

func main() {
        fmt.Println("Hello")
        message := "this is a test"
        log_message(&message)
        go worker(1)
        go worker(2)
        go worker(3)
        go worker(4)
        time.Sleep(3009 * time.Second)
}

func log_message(message *string) {

        if myconn == nil {

                fmt.Println("Setting up myconn!")
                RemoteAddr, err := net.ResolveUDPAddr("udp", udp_dest)
                if err != nil {
                        //fmt.Println("Err,  net.ResolveUDPAddr", err)
                        return
                }
                myconn, err = net.DialUDP("udp", nil, RemoteAddr)

                if err != nil {
                        return
                }
        }

        udp_message := fmt.Sprintf("<30> %s", *message)
        Bytes, _ := myconn.Write([]byte(udp_message))
        log.Printf("Sent %d Bytes to %s\n", Bytes, udp_dest)
}

func worker(tag int) {
        i := 0
        for {
                worker_message := fmt.Sprintf("Some message from worker%d, loop: %d", tag, i)
                log_message(&worker_message)
                // do some work..
                time.Sleep(10 * time.Second)
                i += 1
        }
}

标签: go

解决方案


你快到了。将设置代码移动到一个函数并在启动 goroutine 之前调用它。

func main() {
    if err := setupLog(); err != nil {
        log.Fatal(err)
    }
    fmt.Println("Hello")
    ... same as before
}

func setupLog() error {
    fmt.Println("Setting up myconn!")
    RemoteAddr, err := net.ResolveUDPAddr("udp", udp_dest)
    if err != nil {
        return err
    }
    myconn, err = net.DialUDP("udp", nil, RemoteAddr)
    return err
}

func log_message(message *string) {
    udp_message := fmt.Sprintf("<30> %s", *message)
    Bytes, _ := myconn.Write([]byte(udp_message))
    log.Printf("Sent %d Bytes to %s\n", Bytes, udp_dest)
}

问题中的代码不起作用,因为myconn.


推荐阅读