myTool.go 7.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277
  1. package utils
  2. import (
  3. "fmt"
  4. "net"
  5. "server/global"
  6. "server/model"
  7. "strings"
  8. "time"
  9. )
  10. const (
  11. maxRetries = 3 // 最大重试次数
  12. readTimeout = 5 * time.Second // 读取超时时间
  13. writeTimeout = 5 * time.Second // 写入超时时间
  14. reconnectWait = 2 * time.Second // 重连等待时间
  15. )
  16. // checkConnection 检查连接是否仍然有效
  17. func checkConnection(conn net.Conn) error {
  18. probe := []byte{}
  19. _, err := conn.Write(probe)
  20. return err
  21. }
  22. // checkAndReconnect 检查是否需要重连,并在必要时执行重连
  23. func checkAndReconnect(conn net.Conn) (net.Conn, error) {
  24. remoteAddr := conn.RemoteAddr().String()
  25. // 解析远程地址
  26. addr1, err := net.ResolveTCPAddr("tcp", remoteAddr)
  27. if err != nil {
  28. // 处理错误...
  29. global.GVA_LOG.Error(fmt.Sprintf("解析错误 conn = %s\n", addr1.IP.String()))
  30. }
  31. // 关闭旧连接
  32. if err := conn.Close(); err != nil {
  33. global.GVA_LOG.Error(fmt.Sprintf("Failed to close connection: %v", err))
  34. return nil, err
  35. }
  36. // 解析原始连接的远程地址和网络接口
  37. addr, networkInterface, err := parseRemoteAddr(addr1.IP.String())
  38. if err != nil {
  39. global.GVA_LOG.Error(fmt.Sprintf("Failed to parse remote address: %v", err))
  40. return nil, err
  41. }
  42. // 尝试重新建立连接
  43. newConn, err := net.Dial("tcp", fmt.Sprintf("%s%%%s", addr, networkInterface))
  44. if err != nil {
  45. global.GVA_LOG.Error(fmt.Sprintf("Reconnect failed: %v", err))
  46. return nil, err
  47. }
  48. return newConn, nil
  49. }
  50. // isConnectionClosedError 检查错误是否表明连接被对端强制关闭或已关闭
  51. func isConnectionClosedError(err error) bool {
  52. if ne, ok := err.(*net.OpError); ok {
  53. return strings.Contains(ne.Err.Error(), "forcibly closed") ||
  54. strings.Contains(ne.Err.Error(), "broken pipe") ||
  55. strings.Contains(ne.Err.Error(), "connection reset") ||
  56. strings.Contains(ne.Err.Error(), "use of closed network connection")
  57. }
  58. return false
  59. }
  60. // setDeadlineWithRetry 使用重试机制设置读写截止时间
  61. func setDeadlineWithRetry(conn net.Conn, timeout time.Duration, operation string) error {
  62. for attempts := 0; attempts < maxRetries; attempts++ {
  63. var err error
  64. switch operation {
  65. case "read":
  66. err = conn.SetReadDeadline(time.Now().Add(timeout))
  67. case "write":
  68. err = conn.SetWriteDeadline(time.Now().Add(timeout))
  69. default:
  70. return fmt.Errorf("invalid operation: %s", operation)
  71. }
  72. if err == nil {
  73. return nil
  74. }
  75. if isConnectionClosedError(err) {
  76. global.GVA_LOG.Warn(fmt.Sprintf("Connection check failed due to closed connection, retrying (%d/%d)", attempts+1, maxRetries))
  77. var newConn net.Conn
  78. var reconnErr error
  79. newConn, reconnErr = checkAndReconnect(conn)
  80. if reconnErr != nil {
  81. time.Sleep(reconnectWait) // 等待一段时间后重试
  82. continue // 继续下一次重试
  83. }
  84. conn = newConn
  85. continue // 重试设置截止时间
  86. }
  87. return fmt.Errorf("set %s deadline failed after %d retries: %v", operation, attempts+1, err)
  88. }
  89. return fmt.Errorf("failed to set %s deadline after %d retries", operation, maxRetries)
  90. }
  91. // readWithRetry 使用重试机制进行读取操作
  92. func readWithRetry(buffer []byte, conn net.Conn) (int, error) {
  93. for attempts := 0; attempts < maxRetries; attempts++ {
  94. if err := setDeadlineWithRetry(conn, readTimeout, "read"); err != nil {
  95. return 0, err
  96. }
  97. // 检查连接是否仍然有效
  98. if err := checkConnection(conn); err != nil {
  99. if isConnectionClosedError(err) {
  100. global.GVA_LOG.Warn(fmt.Sprintf("Connection check failed due to closed connection, retrying (%d/%d)", attempts+1, maxRetries))
  101. var newConn net.Conn
  102. var reconnErr error
  103. newConn, reconnErr = checkAndReconnect(conn)
  104. if reconnErr != nil {
  105. time.Sleep(reconnectWait) // 等待一段时间后重试
  106. continue // 继续下一次重试
  107. }
  108. conn = newConn
  109. continue // 重试读取
  110. }
  111. global.GVA_LOG.Warn(fmt.Sprintf("Connection check failed: %v", err))
  112. return 0, fmt.Errorf("connection check failed after %d retries: %v", attempts+1, err)
  113. }
  114. n, err := conn.Read(buffer)
  115. if err == nil {
  116. return n, nil
  117. }
  118. if isConnectionClosedError(err) {
  119. var newConn net.Conn
  120. var reconnErr error
  121. newConn, reconnErr = checkAndReconnect(conn)
  122. if reconnErr != nil {
  123. time.Sleep(reconnectWait) // 等待一段时间后重试
  124. continue // 继续下一次重试
  125. }
  126. conn = newConn
  127. continue // 重试读取
  128. }
  129. return 0, fmt.Errorf("read failed after %d retries: %v", attempts+1, err)
  130. }
  131. return 0, fmt.Errorf("failed to read after %d retries", maxRetries)
  132. }
  133. // writeWithRetry 使用重试机制进行写入操作
  134. func writeWithRetry(frame []byte, conn net.Conn) error {
  135. for attempts := 0; attempts < maxRetries; attempts++ {
  136. if err := setDeadlineWithRetry(conn, writeTimeout, "write"); err != nil {
  137. return err
  138. }
  139. // 检查连接是否仍然有效
  140. if err := checkConnection(conn); err != nil {
  141. if isConnectionClosedError(err) {
  142. global.GVA_LOG.Warn(fmt.Sprintf("Connection check failed due to closed connection, retrying (%d/%d)", attempts+1, maxRetries))
  143. var newConn net.Conn
  144. var reconnErr error
  145. newConn, reconnErr = checkAndReconnect(conn)
  146. if reconnErr != nil {
  147. time.Sleep(reconnectWait) // 等待一段时间后重试
  148. continue // 继续下一次重试
  149. }
  150. conn = newConn
  151. continue // 重试写入
  152. }
  153. return fmt.Errorf("connection check failed after %d retries: %v", attempts+1, err)
  154. }
  155. _, err := conn.Write(frame)
  156. if err == nil {
  157. return nil
  158. }
  159. if isConnectionClosedError(err) {
  160. global.GVA_LOG.Warn(fmt.Sprintf("Write failed due to closed connection, retrying (%d/%d)", attempts+1, maxRetries))
  161. var newConn net.Conn
  162. var reconnErr error
  163. newConn, reconnErr = checkAndReconnect(conn)
  164. if reconnErr != nil {
  165. time.Sleep(reconnectWait) // 等待一段时间后重试
  166. continue // 继续下一次重试
  167. }
  168. conn = newConn
  169. continue // 重试写入
  170. }
  171. return fmt.Errorf("write failed after %d retries: %v", attempts+1, err)
  172. }
  173. return fmt.Errorf("failed to write after %d retries", maxRetries)
  174. }
  175. // ReadDevice 从设备读取数据
  176. func ReadDevice(buffer []byte, conn net.Conn) (int, error) {
  177. return readWithRetry(buffer, conn)
  178. }
  179. // WriteDevice1 向设备写入数据
  180. func WriteDevice1(frame []byte, conn net.Conn) error {
  181. return writeWithRetry(frame, conn)
  182. }
  183. func WriteDevice(frame []byte, conn net.Conn) error {
  184. _, err := conn.Write(frame)
  185. if err != nil {
  186. defer conn.Close()
  187. // 解析远程地址
  188. addr, err := net.ResolveTCPAddr("tcp", conn.RemoteAddr().String())
  189. if err != nil {
  190. // 处理错误...
  191. global.GVA_LOG.Error("解析错误 conn = " + addr.IP.String())
  192. }
  193. model.ConnectionMap1.Delete(addr.IP.String())
  194. return err
  195. }
  196. return nil
  197. }
  198. // 解析远程地址,提取 IP 地址和网络接口名称
  199. func parseRemoteAddr(addr string) (string, string, error) {
  200. parts := strings.Split(addr, "%")
  201. if len(parts) != 2 {
  202. return "", "", fmt.Errorf("invalid remote address format: %s", addr)
  203. }
  204. return parts[0], parts[1], nil
  205. }
  206. func WriteAndReadDevice(frame []byte, conn net.Conn, former, after int) (data []byte, err error) {
  207. // 发送 Modbus RTU 帧
  208. n, err := conn.Write(frame)
  209. if err != nil {
  210. global.GVA_LOG.Error("Error writing to connection:" + err.Error())
  211. return
  212. }
  213. // 等待一段时间以接收响应
  214. time.Sleep(1000 * time.Millisecond)
  215. // 读取响应
  216. buffer := make([]byte, 1024)
  217. n, err = conn.Read(buffer)
  218. if err != nil {
  219. global.GVA_LOG.Error("Error reading from connection:" + err.Error())
  220. return
  221. }
  222. // 检查读取的字节数是否足够
  223. if n < former+after {
  224. err = fmt.Errorf("not enough bytes read to satisfy the slice range")
  225. return
  226. }
  227. // 返回子切片
  228. return buffer[former : n-after], err
  229. }