github.com/angenalZZZ/gofunc@v0.0.0-20210507121333-48ff1be3917b/net/net.go (about) 1 package net 2 3 import ( 4 "log" 5 nt "net" 6 "os" 7 "runtime" 8 "strings" 9 "sync/atomic" 10 "time" 11 12 "github.com/angenalZZZ/gofunc/net/internal/netpoll" 13 ) 14 15 // Action is an action that occurs after the completion of an event. 16 type Action int 17 18 const ( 19 // None indicates that no action should occur following an event. 20 None Action = iota 21 22 // Close closes the connection. 23 Close 24 25 // Shutdown shutdowns the server. 26 Shutdown 27 ) 28 29 var defaultLogger = Logger(log.New(os.Stderr, "", log.LstdFlags)) 30 31 // Logger is used for logging formatted messages. 32 type Logger interface { 33 // Printf must have the same semantics as log.Printf. 34 Printf(format string, args ...interface{}) 35 } 36 37 // Server represents a server context which provides information about the 38 // running server and has control functions for managing state. 39 type Server struct { 40 // svr is the internal server struct. 41 svr *server 42 // Multicore indicates whether the server will be effectively created with multi-cores, if so, 43 // then you must take care of synchronizing the shared data between all event callbacks, otherwise, 44 // it will run the server with single thread. The number of threads in the server will be automatically 45 // assigned to the value of runtime.NumCPU(). 46 Multicore bool 47 48 // The Addr parameter is the listening address that align 49 // with the addr string passed to the Serve function. 50 Addr nt.Addr 51 52 // NumEventLoop is the number of event-loops that the server is using. 53 NumEventLoop int 54 55 // ReusePort indicates whether SO_REUSEPORT is enable. 56 ReusePort bool 57 58 // TCPKeepAlive (SO_KEEPALIVE) socket option. 59 TCPKeepAlive time.Duration 60 } 61 62 // CountConnections counts the number of currently active connections and returns it. 63 func (s Server) CountConnections() (count int) { 64 s.svr.subEventLoopSet.iterate(func(i int, el *eventloop) bool { 65 count += int(atomic.LoadInt32(&el.connCount)) 66 return true 67 }) 68 return 69 } 70 71 // Conn is a interface of gnet connection. 72 type Conn interface { 73 // Context returns a user-defined context. 74 Context() (ctx interface{}) 75 76 // SetContext sets a user-defined context. 77 SetContext(ctx interface{}) 78 79 // LocalAddr is the connection's local socket address. 80 LocalAddr() (addr nt.Addr) 81 82 // RemoteAddr is the connection's remote peer address. 83 RemoteAddr() (addr nt.Addr) 84 85 // Read reads all data from inbound ring-buffer and event-loop-buffer without moving "read" pointer, which means 86 // it does not evict the data from buffers actually and those data will present in buffers until the 87 // ResetBuffer method is called. 88 Read() (buf []byte) 89 90 // ResetBuffer resets the buffers, which means all data in inbound ring-buffer and event-loop-buffer will be evicted. 91 ResetBuffer() 92 93 // ReadN reads bytes with the given length from inbound ring-buffer and event-loop-buffer without moving 94 // "read" pointer, which means it will not evict the data from buffers until the ShiftN method is called, 95 // it reads data from the inbound ring-buffer and event-loop-buffer and returns both bytes and the size of it. 96 // If the length of the available data is less than the given "n", ReadN will return all available data, so you 97 // should make use of the variable "size" returned by it to be aware of the exact length of the returned data. 98 ReadN(n int) (size int, buf []byte) 99 100 // ShiftN shifts "read" pointer in the internal buffers with the given length. 101 ShiftN(n int) (size int) 102 103 // BufferLength returns the length of available data in the internal buffers. 104 BufferLength() (size int) 105 106 // InboundBuffer returns the inbound ring-buffer. 107 //InboundBuffer() *ringbuffer.RingBuffer 108 109 // SendTo writes data for UDP sockets, it allows you to send data back to UDP socket in individual goroutines. 110 SendTo(buf []byte) error 111 112 // AsyncWrite writes data to client/connection asynchronously, usually you would call it in individual goroutines 113 // instead of the event-loop goroutines. 114 AsyncWrite(buf []byte) error 115 116 // Wake triggers a React event for this connection. 117 Wake() error 118 119 // Close closes the current connection. 120 Close() error 121 } 122 123 type ( 124 // EventHandler represents the server events' callbacks for the Serve call. 125 // Each event has an Action return value that is used manage the state 126 // of the connection and server. 127 EventHandler interface { 128 // OnInitComplete fires when the server is ready for accepting connections. 129 // The parameter:server has information and various utilities. 130 OnInitComplete(server Server) (action Action) 131 132 // OnShutdown fires when the server is being shut down, it is called right after 133 // all event-loops and connections are closed. 134 OnShutdown(server Server) 135 136 // OnOpened fires when a new connection has been opened. 137 // The parameter:c has information about the connection such as it's local and remote address. 138 // Parameter:out is the return value which is going to be sent back to the client. 139 OnOpened(c Conn) (out []byte, action Action) 140 141 // OnClosed fires when a connection has been closed. 142 // The parameter:err is the last known connection error. 143 OnClosed(c Conn, err error) (action Action) 144 145 // PreWrite fires just before any data is written to any client socket, this event function is usually used to 146 // put some code of logging/counting/reporting or any prepositive operations before writing data to client. 147 PreWrite() 148 149 // React fires when a connection sends the server data. 150 // Call c.Read() or c.ReadN(n) within the parameter:c to read incoming data from client. 151 // Parameter:out is the return value which is going to be sent back to the client. 152 React(frame []byte, c Conn) (out []byte, action Action) 153 154 // Tick fires immediately after the server starts and will fire again 155 // following the duration specified by the delay return value. 156 Tick() (delay time.Duration, action Action) 157 } 158 159 // EventServer is a built-in implementation of EventHandler which sets up each method with a default implementation, 160 // you can compose it with your own implementation of EventHandler when you don't want to implement all methods 161 // in EventHandler. 162 EventServer struct { 163 } 164 ) 165 166 // OnInitComplete fires when the server is ready for accepting connections. 167 // The parameter:server has information and various utilities. 168 func (es *EventServer) OnInitComplete(svr Server) (action Action) { 169 return 170 } 171 172 // OnShutdown fires when the server is being shut down, it is called right after 173 // all event-loops and connections are closed. 174 func (es *EventServer) OnShutdown(svr Server) { 175 } 176 177 // OnOpened fires when a new connection has been opened. 178 // The parameter:c has information about the connection such as it's local and remote address. 179 // Parameter:out is the return value which is going to be sent back to the client. 180 func (es *EventServer) OnOpened(c Conn) (out []byte, action Action) { 181 return 182 } 183 184 // OnClosed fires when a connection has been closed. 185 // The parameter:err is the last known connection error. 186 func (es *EventServer) OnClosed(c Conn, err error) (action Action) { 187 return 188 } 189 190 // PreWrite fires just before any data is written to any client socket, this event function is usually used to 191 // put some code of logging/counting/reporting or any prepositive operations before writing data to client. 192 func (es *EventServer) PreWrite() { 193 } 194 195 // React fires when a connection sends the server data. 196 // Call c.Read() or c.ReadN(n) within the parameter:c to read incoming data from client. 197 // Parameter:out is the return value which is going to be sent back to the client. 198 func (es *EventServer) React(frame []byte, c Conn) (out []byte, action Action) { 199 return 200 } 201 202 // Tick fires immediately after the server starts and will fire again 203 // following the duration specified by the delay return value. 204 func (es *EventServer) Tick() (delay time.Duration, action Action) { 205 return 206 } 207 208 // Serve starts handling events for the specified address. 209 // 210 // Address should use a scheme prefix and be formatted 211 // like `tcp://192.168.0.10:9851` or `unix://socket`. 212 // Valid network schemes: 213 // tcp - bind to both IPv4 and IPv6 214 // tcp4 - IPv4 215 // tcp6 - IPv6 216 // udp - bind to both IPv4 and IPv6 217 // udp4 - IPv4 218 // udp6 - IPv6 219 // unix - Unix Domain Socket 220 // 221 // The "tcp" network scheme is assumed when one is not specified. 222 func Serve(eventHandler EventHandler, addr string, opts ...Option) (err error) { 223 var ln listener 224 defer func() { 225 ln.close() 226 if ln.network == "unix" { 227 sniffErrorAndLog(os.RemoveAll(ln.addr)) 228 } 229 }() 230 231 options := loadOptions(opts...) 232 233 if options.Logger != nil { 234 defaultLogger = options.Logger 235 } 236 237 ln.network, ln.addr = parseAddr(addr) 238 switch ln.network { 239 case "udp", "udp4", "udp6": 240 if options.ReusePort { 241 ln.pconn, err = netpoll.ReusePortListenPacket(ln.network, ln.addr) 242 } else { 243 ln.pconn, err = nt.ListenPacket(ln.network, ln.addr) 244 } 245 case "unix": 246 sniffErrorAndLog(os.RemoveAll(ln.addr)) 247 if runtime.GOOS == "windows" { 248 err = ErrUnsupportedProtocol 249 break 250 } 251 fallthrough 252 case "tcp", "tcp4", "tcp6": 253 if options.ReusePort { 254 ln.ln, err = netpoll.ReusePortListen(ln.network, ln.addr) 255 } else { 256 ln.ln, err = nt.Listen(ln.network, ln.addr) 257 } 258 default: 259 err = ErrUnsupportedProtocol 260 } 261 if err != nil { 262 return 263 } 264 265 if ln.pconn != nil { 266 ln.lnaddr = ln.pconn.LocalAddr() 267 } else { 268 ln.lnaddr = ln.ln.Addr() 269 } 270 271 if err = ln.renormalize(); err != nil { 272 return 273 } 274 275 return serve(eventHandler, &ln, options) 276 } 277 278 func parseAddr(addr string) (network, address string) { 279 network = "tcp" 280 address = strings.ToLower(addr) 281 if strings.Contains(address, "://") { 282 pair := strings.Split(address, "://") 283 network = pair[0] 284 address = pair[1] 285 } 286 return 287 } 288 289 func sniffErrorAndLog(err error) { 290 if err != nil { 291 defaultLogger.Printf(err.Error()) 292 } 293 }