mirror of
https://github.com/duanhf2012/origin.git
synced 2026-02-03 22:45:13 +08:00
137 lines
2.8 KiB
Go
137 lines
2.8 KiB
Go
package network
|
|
|
|
import (
|
|
"github.com/duanhf2012/origin/log"
|
|
"net"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type TCPServer struct {
|
|
Addr string
|
|
MaxConnNum int
|
|
PendingWriteNum int
|
|
NewAgent func(*TCPConn) Agent
|
|
ln net.Listener
|
|
conns ConnSet
|
|
mutexConns sync.Mutex
|
|
wgLn sync.WaitGroup
|
|
wgConns sync.WaitGroup
|
|
|
|
// msg parser
|
|
LenMsgLen int
|
|
MinMsgLen uint32
|
|
MaxMsgLen uint32
|
|
LittleEndian bool
|
|
msgParser *MsgParser
|
|
netMemPool INetMempool
|
|
}
|
|
|
|
func (server *TCPServer) Start() {
|
|
server.init()
|
|
go server.run()
|
|
}
|
|
|
|
func (server *TCPServer) init() {
|
|
ln, err := net.Listen("tcp", server.Addr)
|
|
if err != nil {
|
|
log.Fatal("%v", err)
|
|
}
|
|
|
|
if server.MaxConnNum <= 0 {
|
|
server.MaxConnNum = 100
|
|
log.Release("invalid MaxConnNum, reset to %v", server.MaxConnNum)
|
|
}
|
|
if server.PendingWriteNum <= 0 {
|
|
server.PendingWriteNum = 100
|
|
log.Release("invalid PendingWriteNum, reset to %v", server.PendingWriteNum)
|
|
}
|
|
if server.NewAgent == nil {
|
|
log.Fatal("NewAgent must not be nil")
|
|
}
|
|
|
|
server.ln = ln
|
|
server.conns = make(ConnSet)
|
|
|
|
// msg parser
|
|
msgParser := NewMsgParser()
|
|
if msgParser.INetMempool == nil {
|
|
msgParser.INetMempool = NewMemAreaPool()
|
|
}
|
|
|
|
msgParser.SetMsgLen(server.LenMsgLen, server.MinMsgLen, server.MaxMsgLen)
|
|
msgParser.SetByteOrder(server.LittleEndian)
|
|
server.msgParser = msgParser
|
|
}
|
|
|
|
func (server *TCPServer) SetNetMempool(mempool INetMempool){
|
|
server.msgParser.INetMempool = mempool
|
|
}
|
|
|
|
func (server *TCPServer) run() {
|
|
server.wgLn.Add(1)
|
|
defer server.wgLn.Done()
|
|
|
|
var tempDelay time.Duration
|
|
for {
|
|
conn, err := server.ln.Accept()
|
|
if err != nil {
|
|
if ne, ok := err.(net.Error); ok && ne.Temporary() {
|
|
if tempDelay == 0 {
|
|
tempDelay = 5 * time.Millisecond
|
|
} else {
|
|
tempDelay *= 2
|
|
}
|
|
if max := 1 * time.Second; tempDelay > max {
|
|
tempDelay = max
|
|
}
|
|
log.Release("accept error: %v; retrying in %v", err, tempDelay)
|
|
time.Sleep(tempDelay)
|
|
continue
|
|
}
|
|
return
|
|
}
|
|
tempDelay = 0
|
|
|
|
server.mutexConns.Lock()
|
|
if len(server.conns) >= server.MaxConnNum {
|
|
server.mutexConns.Unlock()
|
|
conn.Close()
|
|
log.Debug("too many connections")
|
|
continue
|
|
}
|
|
server.conns[conn] = struct{}{}
|
|
server.mutexConns.Unlock()
|
|
|
|
server.wgConns.Add(1)
|
|
|
|
tcpConn := newTCPConn(conn, server.PendingWriteNum, server.msgParser)
|
|
agent := server.NewAgent(tcpConn)
|
|
go func() {
|
|
agent.Run()
|
|
|
|
// cleanup
|
|
tcpConn.Close()
|
|
server.mutexConns.Lock()
|
|
delete(server.conns, conn)
|
|
server.mutexConns.Unlock()
|
|
agent.OnClose()
|
|
|
|
server.wgConns.Done()
|
|
}()
|
|
}
|
|
}
|
|
|
|
func (server *TCPServer) Close() {
|
|
server.ln.Close()
|
|
server.wgLn.Wait()
|
|
|
|
server.mutexConns.Lock()
|
|
for conn := range server.conns {
|
|
conn.Close()
|
|
}
|
|
server.conns = nil
|
|
server.mutexConns.Unlock()
|
|
server.wgConns.Wait()
|
|
}
|