gudp_func.go 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. // Copyright GoFrame Author(https://goframe.org). All Rights Reserved.
  2. //
  3. // This Source Code Form is subject to the terms of the MIT License.
  4. // If a copy of the MIT was not distributed with this file,
  5. // You can obtain one at https://github.com/gogf/gf.
  6. package gudp
  7. import (
  8. "net"
  9. "github.com/gogf/gf/v2/errors/gerror"
  10. )
  11. // NewNetConn creates and returns a *net.UDPConn with given addresses.
  12. func NewNetConn(remoteAddress string, localAddress ...string) (*net.UDPConn, error) {
  13. var (
  14. err error
  15. remoteAddr *net.UDPAddr
  16. localAddr *net.UDPAddr
  17. network = `udp`
  18. )
  19. remoteAddr, err = net.ResolveUDPAddr(network, remoteAddress)
  20. if err != nil {
  21. return nil, gerror.Wrapf(
  22. err,
  23. `net.ResolveUDPAddr failed for network "%s", address "%s"`,
  24. network, remoteAddress,
  25. )
  26. }
  27. if len(localAddress) > 0 {
  28. localAddr, err = net.ResolveUDPAddr(network, localAddress[0])
  29. if err != nil {
  30. return nil, gerror.Wrapf(
  31. err,
  32. `net.ResolveUDPAddr failed for network "%s", address "%s"`,
  33. network, localAddress[0],
  34. )
  35. }
  36. }
  37. conn, err := net.DialUDP(network, localAddr, remoteAddr)
  38. if err != nil {
  39. return nil, gerror.Wrapf(
  40. err,
  41. `net.DialUDP failed for network "%s", local "%s", remote "%s"`,
  42. network, localAddr.String(), remoteAddr.String(),
  43. )
  44. }
  45. return conn, nil
  46. }
  47. // Send writes data to `address` using UDP connection and then closes the connection.
  48. // Note that it is used for short connection usage.
  49. func Send(address string, data []byte, retry ...Retry) error {
  50. conn, err := NewConn(address)
  51. if err != nil {
  52. return err
  53. }
  54. defer conn.Close()
  55. return conn.Send(data, retry...)
  56. }
  57. // SendRecv writes data to `address` using UDP connection, reads response and then closes the connection.
  58. // Note that it is used for short connection usage.
  59. func SendRecv(address string, data []byte, receive int, retry ...Retry) ([]byte, error) {
  60. conn, err := NewConn(address)
  61. if err != nil {
  62. return nil, err
  63. }
  64. defer conn.Close()
  65. return conn.SendRecv(data, receive, retry...)
  66. }
  67. // MustGetFreePort performs as GetFreePort, but it panics if any error occurs.
  68. func MustGetFreePort() (port int) {
  69. port, err := GetFreePort()
  70. if err != nil {
  71. panic(err)
  72. }
  73. return port
  74. }
  75. // GetFreePort retrieves and returns a port that is free.
  76. func GetFreePort() (port int, err error) {
  77. var (
  78. network = `udp`
  79. address = `:0`
  80. )
  81. resolvedAddr, err := net.ResolveUDPAddr(network, address)
  82. if err != nil {
  83. return 0, gerror.Wrapf(
  84. err,
  85. `net.ResolveUDPAddr failed for network "%s", address "%s"`,
  86. network, address,
  87. )
  88. }
  89. l, err := net.ListenUDP(network, resolvedAddr)
  90. if err != nil {
  91. return 0, gerror.Wrapf(
  92. err,
  93. `net.ListenUDP failed for network "%s", address "%s"`,
  94. network, resolvedAddr.String(),
  95. )
  96. }
  97. port = l.LocalAddr().(*net.UDPAddr).Port
  98. _ = l.Close()
  99. return
  100. }
  101. // GetFreePorts retrieves and returns specified number of ports that are free.
  102. func GetFreePorts(count int) (ports []int, err error) {
  103. var (
  104. network = `udp`
  105. address = `:0`
  106. )
  107. for i := 0; i < count; i++ {
  108. resolvedAddr, err := net.ResolveUDPAddr(network, address)
  109. if err != nil {
  110. return nil, gerror.Wrapf(
  111. err,
  112. `net.ResolveUDPAddr failed for network "%s", address "%s"`,
  113. network, address,
  114. )
  115. }
  116. l, err := net.ListenUDP(network, resolvedAddr)
  117. if err != nil {
  118. return nil, gerror.Wrapf(
  119. err,
  120. `net.ListenUDP failed for network "%s", address "%s"`,
  121. network, resolvedAddr.String(),
  122. )
  123. }
  124. ports = append(ports, l.LocalAddr().(*net.UDPAddr).Port)
  125. _ = l.Close()
  126. }
  127. return ports, nil
  128. }