gudp_conn.go 5.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205
  1. // Copyright 2018 gf Author(https://github.com/gogf/gf). 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. "io"
  9. "net"
  10. "time"
  11. )
  12. // Conn handles the UDP connection.
  13. type Conn struct {
  14. *net.UDPConn // Underlying UDP connection.
  15. remoteAddr *net.UDPAddr // Remote address.
  16. recvDeadline time.Time // Timeout point for reading data.
  17. sendDeadline time.Time // Timeout point for writing data.
  18. recvBufferWait time.Duration // Interval duration for reading buffer.
  19. }
  20. const (
  21. gDEFAULT_RETRY_INTERVAL = 100 * time.Millisecond // Retry interval.
  22. gDEFAULT_READ_BUFFER_SIZE = 1024 // (Byte)Buffer size.
  23. gRECV_ALL_WAIT_TIMEOUT = time.Millisecond // Default interval for reading buffer.
  24. )
  25. type Retry struct {
  26. Count int // Max retry count.
  27. Interval time.Duration // Retry interval.
  28. }
  29. // NewConn creates UDP connection to <remoteAddress>.
  30. // The optional parameter <localAddress> specifies the local address for connection.
  31. func NewConn(remoteAddress string, localAddress ...string) (*Conn, error) {
  32. if conn, err := NewNetConn(remoteAddress, localAddress...); err == nil {
  33. return NewConnByNetConn(conn), nil
  34. } else {
  35. return nil, err
  36. }
  37. }
  38. // NewConnByNetConn creates a UDP connection object with given *net.UDPConn object.
  39. func NewConnByNetConn(udp *net.UDPConn) *Conn {
  40. return &Conn{
  41. UDPConn: udp,
  42. recvDeadline: time.Time{},
  43. sendDeadline: time.Time{},
  44. recvBufferWait: gRECV_ALL_WAIT_TIMEOUT,
  45. }
  46. }
  47. // Send writes data to remote address.
  48. func (c *Conn) Send(data []byte, retry ...Retry) (err error) {
  49. for {
  50. if c.remoteAddr != nil {
  51. _, err = c.WriteToUDP(data, c.remoteAddr)
  52. } else {
  53. _, err = c.Write(data)
  54. }
  55. if err != nil {
  56. // Connection closed.
  57. if err == io.EOF {
  58. return err
  59. }
  60. // Still failed even after retrying.
  61. if len(retry) == 0 || retry[0].Count == 0 {
  62. return err
  63. }
  64. if len(retry) > 0 {
  65. retry[0].Count--
  66. if retry[0].Interval == 0 {
  67. retry[0].Interval = gDEFAULT_RETRY_INTERVAL
  68. }
  69. time.Sleep(retry[0].Interval)
  70. }
  71. } else {
  72. return nil
  73. }
  74. }
  75. }
  76. // Recv receives and returns data from remote address.
  77. // The parameter <buffer> is used for customizing the receiving buffer size. If <buffer> <= 0,
  78. // it uses the default buffer size, which is 1024 byte.
  79. //
  80. // There's package border in UDP protocol, we can receive a complete package if specified
  81. // buffer size is big enough. VERY NOTE that we should receive the complete package in once
  82. // or else the leftover package data would be dropped.
  83. func (c *Conn) Recv(buffer int, retry ...Retry) ([]byte, error) {
  84. var err error // Reading error.
  85. var size int // Reading size.
  86. var data []byte // Buffer object.
  87. var remoteAddr *net.UDPAddr // Current remote address for reading.
  88. if buffer > 0 {
  89. data = make([]byte, buffer)
  90. } else {
  91. data = make([]byte, gDEFAULT_READ_BUFFER_SIZE)
  92. }
  93. for {
  94. size, remoteAddr, err = c.ReadFromUDP(data)
  95. if err == nil {
  96. c.remoteAddr = remoteAddr
  97. }
  98. if err != nil {
  99. // Connection closed.
  100. if err == io.EOF {
  101. break
  102. }
  103. if len(retry) > 0 {
  104. // It fails even it retried.
  105. if retry[0].Count == 0 {
  106. break
  107. }
  108. retry[0].Count--
  109. if retry[0].Interval == 0 {
  110. retry[0].Interval = gDEFAULT_RETRY_INTERVAL
  111. }
  112. time.Sleep(retry[0].Interval)
  113. continue
  114. }
  115. break
  116. }
  117. break
  118. }
  119. return data[:size], err
  120. }
  121. // SendRecv writes data to connection and blocks reading response.
  122. func (c *Conn) SendRecv(data []byte, receive int, retry ...Retry) ([]byte, error) {
  123. if err := c.Send(data, retry...); err == nil {
  124. return c.Recv(receive, retry...)
  125. } else {
  126. return nil, err
  127. }
  128. }
  129. // RecvWithTimeout reads data from remote address with timeout.
  130. func (c *Conn) RecvWithTimeout(length int, timeout time.Duration, retry ...Retry) (data []byte, err error) {
  131. if err := c.SetRecvDeadline(time.Now().Add(timeout)); err != nil {
  132. return nil, err
  133. }
  134. defer c.SetRecvDeadline(time.Time{})
  135. data, err = c.Recv(length, retry...)
  136. return
  137. }
  138. // SendWithTimeout writes data to connection with timeout.
  139. func (c *Conn) SendWithTimeout(data []byte, timeout time.Duration, retry ...Retry) (err error) {
  140. if err := c.SetSendDeadline(time.Now().Add(timeout)); err != nil {
  141. return err
  142. }
  143. defer c.SetSendDeadline(time.Time{})
  144. err = c.Send(data, retry...)
  145. return
  146. }
  147. // SendRecvWithTimeout writes data to connection and reads response with timeout.
  148. func (c *Conn) SendRecvWithTimeout(data []byte, receive int, timeout time.Duration, retry ...Retry) ([]byte, error) {
  149. if err := c.Send(data, retry...); err == nil {
  150. return c.RecvWithTimeout(receive, timeout, retry...)
  151. } else {
  152. return nil, err
  153. }
  154. }
  155. func (c *Conn) SetDeadline(t time.Time) error {
  156. err := c.UDPConn.SetDeadline(t)
  157. if err == nil {
  158. c.recvDeadline = t
  159. c.sendDeadline = t
  160. }
  161. return err
  162. }
  163. func (c *Conn) SetRecvDeadline(t time.Time) error {
  164. err := c.SetReadDeadline(t)
  165. if err == nil {
  166. c.recvDeadline = t
  167. }
  168. return err
  169. }
  170. func (c *Conn) SetSendDeadline(t time.Time) error {
  171. err := c.SetWriteDeadline(t)
  172. if err == nil {
  173. c.sendDeadline = t
  174. }
  175. return err
  176. }
  177. // SetRecvBufferWait sets the buffer waiting timeout when reading all data from connection.
  178. // The waiting duration cannot be too long which might delay receiving data from remote address.
  179. func (c *Conn) SetRecvBufferWait(d time.Duration) {
  180. c.recvBufferWait = d
  181. }
  182. // RemoteAddr returns the remote address of current UDP connection.
  183. // Note that it cannot use c.conn.RemoteAddr() as it's nil.
  184. func (c *Conn) RemoteAddr() net.Addr {
  185. //return c.conn.RemoteAddr()
  186. return c.remoteAddr
  187. }