如何使用go支持与UDP服务器的并发连接

时间:2015-02-08 22:55:23

标签: go

我正在玩我的第一个基本udp服务器,我想知道如何支持并发连接?我认为使用我的代码只能一次获得连接以便处理它,使用tcp简单服务器,事情似乎比在这种情况下更清楚,抛出goroutine来处理数据,但在这里我很丢了,谢谢你。

func main() {
    ListenerUDP("127.0.0.1", 1111)
}

func ListenerUDP(ip string, port int) {
    buffer := make([]byte, 1024)

    log.Println("Listener Started!")
    addr := net.UDPAddr{
        Port: port,
        IP:   net.ParseIP(ip),
    }

    conn, err := net.ListenUDP("udp", &addr)
    if err != nil {
        log.Fatalf("Error Listening:%s\n", err.Error())
        panic(err)
    }
    defer conn.Close()

    for {
        _, remoteAddr, err := conn.ReadFromUDP(buffer[0:])
        if err != nil {
            log.Fatalf("Error:%s\n", err)
        }
        // Process data here? using a > go something()?
        fmt.Printf("Data:%s From:%v\n", buffer, remoteAddr)
    }

}

1 个答案:

答案 0 :(得分:5)

UDP is a connectionless protocol - 主机首先发送数据包而不建立连接。

要让多个核心并行处理UDP数据包,您可能会启动一堆goroutine,每个goroutine都执行ReadFromUDP循环:

package main

import (
        "fmt"
        "net"
        "runtime"
)

func listen(connection *net.UDPConn, quit chan struct{}) {
        buffer := make([]byte, 1024)
        n, remoteAddr, err := 0, new(net.UDPAddr), error(nil)
        for err == nil {
                n, remoteAddr, err = connection.ReadFromUDP(buffer)
                // you might copy out the contents of the packet here, to
                // `var r myapp.Request`, say, and `go handleRequest(r)` (or
                // send it down a channel) to free up the listening
                // goroutine. you do *need* to copy then, though,
                // because you've only made one buffer per listen().
                fmt.Println("from", remoteAddr, "-", buffer[:n])
        }
        fmt.Println("listener failed - ", err)
        quit <- struct{}{}
}

func main() {
        addr := net.UDPAddr{
                Port: 12345,
                IP:   net.IP{127, 0, 0, 1},
        }
        connection, err := net.ListenUDP("udp", &addr)
        if err != nil {
                panic(err)
        }
        quit := make(chan struct{})
        for i := 0; i < runtime.NumCPU(); i++ {
                go listen(connection, quit)
        }
        <-quit // hang until an error
}