github.com/searKing/golang/go@v1.2.74/net/tcp/server.go (about) 1 // Copyright 2020 The searKing Author. All rights reserved. 2 // Use of this source code is governed by a BSD-style 3 // license that can be found in the LICENSE file. 4 5 package tcp 6 7 import ( 8 "context" 9 "io" 10 "log" 11 "net" 12 "sync" 13 "time" 14 15 "github.com/searKing/golang/go/sync/atomic" 16 time_ "github.com/searKing/golang/go/time" 17 "github.com/searKing/golang/go/util/object" 18 ) 19 20 type Handler interface { 21 OnOpenHandler 22 OnMsgReadHandler 23 OnMsgHandleHandler 24 OnCloseHandler 25 OnErrorHandler 26 } 27 28 func NewServerFunc( 29 onOpen OnOpenHandler, 30 onMsgRead OnMsgReadHandler, 31 onMsgHandle OnMsgHandleHandler, 32 onClose OnCloseHandler, 33 onError OnErrorHandler) *Server { 34 return &Server{ 35 onOpenHandler: object.RequireNonNullElse(onOpen, NopOnOpenHandler).(OnOpenHandler), 36 onMsgReadHandler: object.RequireNonNullElse(onMsgRead, NopOnMsgReadHandler).(OnMsgReadHandler), 37 onMsgHandleHandler: object.RequireNonNullElse(onMsgHandle, NopOnMsgHandleHandler).(OnMsgHandleHandler), 38 onCloseHandler: object.RequireNonNullElse(onClose, NopOnCloseHandler).(OnCloseHandler), 39 onErrorHandler: object.RequireNonNullElse(onError, NopOnErrorHandler).(OnErrorHandler), 40 } 41 } 42 func NewServer(h Handler) *Server { 43 return NewServerFunc(h, h, h, h, h) 44 } 45 46 type Server struct { 47 Addr string // TCP address to listen on, ":tcp" if empty 48 onOpenHandler OnOpenHandler 49 onMsgReadHandler OnMsgReadHandler 50 onMsgHandleHandler OnMsgHandleHandler 51 onCloseHandler OnCloseHandler 52 onErrorHandler OnErrorHandler 53 54 ReadTimeout time.Duration 55 WriteTimeout time.Duration 56 IdleTimeout time.Duration 57 MaxBytes int 58 59 ErrorLog *log.Logger 60 61 mu sync.Mutex 62 listeners map[*net.Listener]struct{} 63 activeConn map[*conn]struct{} 64 doneChan chan struct{} 65 onShutdown []func() 66 67 // server state 68 inShutdown atomic.Bool 69 70 // ConnState specifies an optional callback function that is 71 // called when a client connection changes state. See the 72 // ConnState type and associated constants for details. 73 ConnState func(net.Conn, ConnState) 74 } 75 76 func (srv *Server) CheckError(w io.Writer, r io.Reader, err error) error { 77 if err == nil { 78 return nil 79 } 80 return srv.onErrorHandler.OnError(w, r, err) 81 } 82 83 func (srv *Server) ListenAndServe() error { 84 if srv.shuttingDown() { 85 return srv.CheckError(nil, nil, ErrServerClosed) 86 } 87 addr := srv.Addr 88 if addr == "" { 89 addr = ":tcp" 90 } 91 ln, err := net.Listen("tcp", addr) 92 if srv.CheckError(nil, nil, err) != nil { 93 return err 94 } 95 return srv.Serve(tcpKeepAliveListener{ln.(*net.TCPListener)}) 96 } 97 98 func (srv *Server) Serve(l net.Listener) error { 99 l = &onceCloseListener{Listener: l} 100 defer l.Close() 101 102 // how long to sleep on accept failure 103 var tempDelay = time_.NewExponentialBackOff( 104 time_.WithExponentialBackOffOptionInitialInterval(5*time.Millisecond), 105 time_.WithExponentialBackOffOptionMaxInterval(time.Second), 106 time_.WithExponentialBackOffOptionMaxElapsedDuration(-1), 107 time_.WithExponentialBackOffOptionMaxElapsedCount(-1)) 108 ctx := context.WithValue(context.Background(), ServerContextKey, srv) 109 for { 110 rw, e := l.Accept() 111 if e != nil { 112 // return if server is cancaled, means normally close 113 select { 114 case <-srv.getDoneChan(): 115 return ErrServerClosed 116 default: 117 } 118 // retry if it's recoverable 119 if ne, ok := e.(net.Error); ok && ne.Temporary() { 120 delay, ok := tempDelay.NextBackOff() 121 if !ok { 122 srv.logf("http: Accept error: %v; retried canceled as time exceed(%v)", e, tempDelay.GetMaxElapsedDuration()) 123 // return if timeout 124 return srv.CheckError(nil, nil, e) 125 } 126 srv.logf("http: Accept error: %v; retrying in %v", e, delay) 127 time.Sleep(delay) 128 continue 129 } 130 // return otherwise 131 return srv.CheckError(nil, nil, e) 132 } 133 tempDelay.Reset() 134 135 // takeover the connect 136 c := srv.newConn(rw) 137 // Handle websocket On 138 err := srv.onOpenHandler.OnOpen(c.rwc) 139 if err = srv.CheckError(c.w, c.r, err); err != nil { 140 c.close() 141 return err 142 } 143 c.setState(c.rwc, StateNew) // before Serve can return 144 go c.serve(ctx) 145 } 146 } 147 148 func (srv *Server) trackConn(c *conn, add bool) { 149 srv.mu.Lock() 150 defer srv.mu.Unlock() 151 if srv.activeConn == nil { 152 srv.activeConn = make(map[*conn]struct{}) 153 } 154 if add { 155 srv.activeConn[c] = struct{}{} 156 } else { 157 delete(srv.activeConn, c) 158 } 159 } 160 161 // Create new connection from rwc. 162 func (srv *Server) newConn(rwc net.Conn) *conn { 163 c := &conn{ 164 server: srv, 165 rwc: rwc, 166 } 167 return c 168 } 169 170 func (srv *Server) logf(format string, args ...interface{}) { 171 if srv.ErrorLog != nil { 172 srv.ErrorLog.Printf(format, args...) 173 } else { 174 log.Printf(format, args...) 175 } 176 } 177 178 func ListenAndServe(addr string, readMsg OnMsgReadHandler, handleMsg OnMsgHandleHandler) error { 179 server := &Server{Addr: addr, onMsgReadHandler: readMsg, onMsgHandleHandler: handleMsg} 180 return server.ListenAndServe() 181 }