gtcp_server.go 5.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  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 gtcp
  7. import (
  8. "crypto/tls"
  9. "fmt"
  10. "net"
  11. "sync"
  12. "github.com/gogf/gf/v2/container/gmap"
  13. "github.com/gogf/gf/v2/errors/gcode"
  14. "github.com/gogf/gf/v2/errors/gerror"
  15. "github.com/gogf/gf/v2/text/gstr"
  16. "github.com/gogf/gf/v2/util/gconv"
  17. )
  18. const (
  19. // FreePortAddress marks the server listens using random free port.
  20. FreePortAddress = ":0"
  21. )
  22. const (
  23. defaultServer = "default"
  24. )
  25. // Server is a TCP server.
  26. type Server struct {
  27. mu sync.Mutex // Used for Server.listen concurrent safety. -- The golang test with data race checks this.
  28. listen net.Listener // TCP address listener.
  29. address string // Server listening address.
  30. handler func(*Conn) // Connection handler.
  31. tlsConfig *tls.Config // TLS configuration.
  32. }
  33. // Map for name to server, for singleton purpose.
  34. var serverMapping = gmap.NewStrAnyMap(true)
  35. // GetServer returns the TCP server with specified `name`,
  36. // or it returns a new normal TCP server named `name` if it does not exist.
  37. // The parameter `name` is used to specify the TCP server
  38. func GetServer(name ...interface{}) *Server {
  39. serverName := defaultServer
  40. if len(name) > 0 && name[0] != "" {
  41. serverName = gconv.String(name[0])
  42. }
  43. return serverMapping.GetOrSetFuncLock(serverName, func() interface{} {
  44. return NewServer("", nil)
  45. }).(*Server)
  46. }
  47. // NewServer creates and returns a new normal TCP server.
  48. // The parameter `name` is optional, which is used to specify the instance name of the server.
  49. func NewServer(address string, handler func(*Conn), name ...string) *Server {
  50. s := &Server{
  51. address: address,
  52. handler: handler,
  53. }
  54. if len(name) > 0 && name[0] != "" {
  55. serverMapping.Set(name[0], s)
  56. }
  57. return s
  58. }
  59. // NewServerTLS creates and returns a new TCP server with TLS support.
  60. // The parameter `name` is optional, which is used to specify the instance name of the server.
  61. func NewServerTLS(address string, tlsConfig *tls.Config, handler func(*Conn), name ...string) *Server {
  62. s := NewServer(address, handler, name...)
  63. s.SetTLSConfig(tlsConfig)
  64. return s
  65. }
  66. // NewServerKeyCrt creates and returns a new TCP server with TLS support.
  67. // The parameter `name` is optional, which is used to specify the instance name of the server.
  68. func NewServerKeyCrt(address, crtFile, keyFile string, handler func(*Conn), name ...string) (*Server, error) {
  69. s := NewServer(address, handler, name...)
  70. if err := s.SetTLSKeyCrt(crtFile, keyFile); err != nil {
  71. return nil, err
  72. }
  73. return s, nil
  74. }
  75. // SetAddress sets the listening address for server.
  76. func (s *Server) SetAddress(address string) {
  77. s.address = address
  78. }
  79. // GetAddress get the listening address for server.
  80. func (s *Server) GetAddress() string {
  81. return s.address
  82. }
  83. // SetHandler sets the connection handler for server.
  84. func (s *Server) SetHandler(handler func(*Conn)) {
  85. s.handler = handler
  86. }
  87. // SetTLSKeyCrt sets the certificate and key file for TLS configuration of server.
  88. func (s *Server) SetTLSKeyCrt(crtFile, keyFile string) error {
  89. tlsConfig, err := LoadKeyCrt(crtFile, keyFile)
  90. if err != nil {
  91. return err
  92. }
  93. s.tlsConfig = tlsConfig
  94. return nil
  95. }
  96. // SetTLSConfig sets the TLS configuration of server.
  97. func (s *Server) SetTLSConfig(tlsConfig *tls.Config) {
  98. s.tlsConfig = tlsConfig
  99. }
  100. // Close closes the listener and shutdowns the server.
  101. func (s *Server) Close() error {
  102. s.mu.Lock()
  103. defer s.mu.Unlock()
  104. if s.listen == nil {
  105. return nil
  106. }
  107. return s.listen.Close()
  108. }
  109. // Run starts running the TCP Server.
  110. func (s *Server) Run() (err error) {
  111. if s.handler == nil {
  112. err = gerror.NewCode(gcode.CodeMissingConfiguration, "start running failed: socket handler not defined")
  113. return
  114. }
  115. if s.tlsConfig != nil {
  116. // TLS Server
  117. s.mu.Lock()
  118. s.listen, err = tls.Listen("tcp", s.address, s.tlsConfig)
  119. s.mu.Unlock()
  120. if err != nil {
  121. err = gerror.Wrapf(err, `tls.Listen failed for address "%s"`, s.address)
  122. return
  123. }
  124. } else {
  125. // Normal Server
  126. var tcpAddr *net.TCPAddr
  127. if tcpAddr, err = net.ResolveTCPAddr("tcp", s.address); err != nil {
  128. err = gerror.Wrapf(err, `net.ResolveTCPAddr failed for address "%s"`, s.address)
  129. return err
  130. }
  131. s.mu.Lock()
  132. s.listen, err = net.ListenTCP("tcp", tcpAddr)
  133. s.mu.Unlock()
  134. if err != nil {
  135. err = gerror.Wrapf(err, `net.ListenTCP failed for address "%s"`, s.address)
  136. return err
  137. }
  138. }
  139. // Listening loop.
  140. for {
  141. var conn net.Conn
  142. if conn, err = s.listen.Accept(); err != nil {
  143. err = gerror.Wrapf(err, `Listener.Accept failed`)
  144. return err
  145. } else if conn != nil {
  146. go s.handler(NewConnByNetConn(conn))
  147. }
  148. }
  149. }
  150. // GetListenedAddress retrieves and returns the address string which are listened by current server.
  151. func (s *Server) GetListenedAddress() string {
  152. if !gstr.Contains(s.address, FreePortAddress) {
  153. return s.address
  154. }
  155. var (
  156. address = s.address
  157. listenedPort = s.GetListenedPort()
  158. )
  159. address = gstr.Replace(address, FreePortAddress, fmt.Sprintf(`:%d`, listenedPort))
  160. return address
  161. }
  162. // GetListenedPort retrieves and returns one port which is listened to by current server.
  163. func (s *Server) GetListenedPort() int {
  164. s.mu.Lock()
  165. defer s.mu.Unlock()
  166. if ln := s.listen; ln != nil {
  167. return ln.Addr().(*net.TCPAddr).Port
  168. }
  169. return -1
  170. }