英文:
How support concurrent connections with a UDP Server using 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)
}
// 在这里处理数据?使用 go something()?
fmt.Printf("Data:%s From:%v\n", buffer, remoteAddr)
}
}
你可以使用goroutine来处理并发连接。在for
循环中,你可以使用go
关键字启动一个goroutine来处理每个连接。这样,你的服务器就可以同时处理多个连接了。例如,你可以将处理数据的代码放在一个函数中,然后使用go
关键字调用该函数:
go processConnection(buffer, remoteAddr)
这样,每当有新的连接到达时,就会启动一个新的goroutine来处理它。请确保在处理连接时使用适当的同步机制,以避免竞态条件和数据访问冲突。
英文:
I'm playing with my first basic udp server and I wondering how support concurrent connections? I think with my code only can get a connection at a time in order to process it, with a tcp simple server the things seems to be more clear than on this case, throwing a goroutine to process the data, but here I'm very lost, thanks in advance.
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
得分: 7
UDP是一种无连接的协议,主机在建立连接之前就发送数据包。
为了让多个核心并行处理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)
// 在这里你可以将数据包的内容复制出来,比如到`var r myapp.Request`,
// 然后`go handleRequest(r)`(或将其发送到一个通道)以释放监听的goroutine。
// 不过你确实需要复制数据,因为你每个`listen()`只创建了一个缓冲区。
fmt.Println("来自", remoteAddr, "-", buffer[:n])
}
fmt.Println("监听失败 - ", 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 // 等待直到出现错误
}
英文:
UDP is a connectionless protocol--hosts send packets without establishing a connection first.
To get multiple cores handling UDP packets in parallel, you might start a bunch of goroutines that each do the ReadFromUDP
loop:
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
}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论