How support concurrent connections with a UDP Server using go

huangapple go评论109阅读模式
英文:

How support concurrent connections with a UDP Server using go

问题

我正在玩我的第一个基本UDP服务器,我想知道如何支持并发连接?我觉得我的代码只能一次处理一个连接,对于处理数据,使用一个TCP简单服务器似乎比这种情况更清晰,可以使用goroutine来处理数据,但是在这里我很迷茫,提前谢谢。

  1. func main() {
  2. ListenerUDP("127.0.0.1", 1111)
  3. }
  4. func ListenerUDP(ip string, port int) {
  5. buffer := make([]byte, 1024)
  6. log.Println("Listener Started!")
  7. addr := net.UDPAddr{
  8. Port: port,
  9. IP: net.ParseIP(ip),
  10. }
  11. conn, err := net.ListenUDP("udp", &addr)
  12. if err != nil {
  13. log.Fatalf("Error Listening:%s\n", err.Error())
  14. panic(err)
  15. }
  16. defer conn.Close()
  17. for {
  18. _, remoteAddr, err := conn.ReadFromUDP(buffer[0:])
  19. if err != nil {
  20. log.Fatalf("Error:%s\n", err)
  21. }
  22. // 在这里处理数据?使用 go something()?
  23. fmt.Printf("Data:%s From:%v\n", buffer, remoteAddr)
  24. }
  25. }

你可以使用goroutine来处理并发连接。在for循环中,你可以使用go关键字启动一个goroutine来处理每个连接。这样,你的服务器就可以同时处理多个连接了。例如,你可以将处理数据的代码放在一个函数中,然后使用go关键字调用该函数:

  1. 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.

  1. func main() {
  2. ListenerUDP("127.0.0.1", 1111)
  3. }
  4. func ListenerUDP(ip string, port int) {
  5. buffer := make([]byte, 1024)
  6. log.Println("Listener Started!")
  7. addr := net.UDPAddr{
  8. Port: port,
  9. IP: net.ParseIP(ip),
  10. }
  11. conn, err := net.ListenUDP("udp", &addr)
  12. if err != nil {
  13. log.Fatalf("Error Listening:%s\n", err.Error())
  14. panic(err)
  15. }
  16. defer conn.Close()
  17. for {
  18. _, remoteAddr, err := conn.ReadFromUDP(buffer[0:])
  19. if err != nil {
  20. log.Fatalf("Error:%s\n", err)
  21. }
  22. // Process data here? using a > go something()?
  23. fmt.Printf("Data:%s From:%v\n", buffer, remoteAddr)
  24. }
  25. }

答案1

得分: 7

UDP是一种无连接的协议,主机在建立连接之前就发送数据包。

为了让多个核心并行处理UDP数据包,你可以启动一组goroutine,每个goroutine都执行ReadFromUDP循环:

  1. package main
  2. import (
  3. "fmt"
  4. "net"
  5. "runtime"
  6. )
  7. func listen(connection *net.UDPConn, quit chan struct{}) {
  8. buffer := make([]byte, 1024)
  9. n, remoteAddr, err := 0, new(net.UDPAddr), error(nil)
  10. for err == nil {
  11. n, remoteAddr, err = connection.ReadFromUDP(buffer)
  12. // 在这里你可以将数据包的内容复制出来,比如到`var r myapp.Request`,
  13. // 然后`go handleRequest(r)`(或将其发送到一个通道)以释放监听的goroutine。
  14. // 不过你确实需要复制数据,因为你每个`listen()`只创建了一个缓冲区。
  15. fmt.Println("来自", remoteAddr, "-", buffer[:n])
  16. }
  17. fmt.Println("监听失败 - ", err)
  18. quit <- struct{}{}
  19. }
  20. func main() {
  21. addr := net.UDPAddr{
  22. Port: 12345,
  23. IP: net.IP{127, 0, 0, 1},
  24. }
  25. connection, err := net.ListenUDP("udp", &addr)
  26. if err != nil {
  27. panic(err)
  28. }
  29. quit := make(chan struct{})
  30. for i := 0; i < runtime.NumCPU(); i++ {
  31. go listen(connection, quit)
  32. }
  33. <-quit // 等待直到出现错误
  34. }
英文:

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:

  1. package main
  2. import (
  3. &quot;fmt&quot;
  4. &quot;net&quot;
  5. &quot;runtime&quot;
  6. )
  7. func listen(connection *net.UDPConn, quit chan struct{}) {
  8. buffer := make([]byte, 1024)
  9. n, remoteAddr, err := 0, new(net.UDPAddr), error(nil)
  10. for err == nil {
  11. n, remoteAddr, err = connection.ReadFromUDP(buffer)
  12. // you might copy out the contents of the packet here, to
  13. // `var r myapp.Request`, say, and `go handleRequest(r)` (or
  14. // send it down a channel) to free up the listening
  15. // goroutine. you do *need* to copy then, though,
  16. // because you&#39;ve only made one buffer per listen().
  17. fmt.Println(&quot;from&quot;, remoteAddr, &quot;-&quot;, buffer[:n])
  18. }
  19. fmt.Println(&quot;listener failed - &quot;, err)
  20. quit &lt;- struct{}{}
  21. }
  22. func main() {
  23. addr := net.UDPAddr{
  24. Port: 12345,
  25. IP: net.IP{127, 0, 0, 1},
  26. }
  27. connection, err := net.ListenUDP(&quot;udp&quot;, &amp;addr)
  28. if err != nil {
  29. panic(err)
  30. }
  31. quit := make(chan struct{})
  32. for i := 0; i &lt; runtime.NumCPU(); i++ {
  33. go listen(connection, quit)
  34. }
  35. &lt;-quit // hang until an error
  36. }

huangapple
  • 本文由 发表于 2015年2月9日 06:55:22
  • 转载请务必保留本文链接:https://go.coder-hub.com/28400340.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定