mirror of
https://github.com/duanhf2012/origin.git
synced 2026-02-16 09:24:47 +08:00
提交origin2.0版本
This commit is contained in:
127
network/tcp_server.go
Normal file
127
network/tcp_server.go
Normal file
@@ -0,0 +1,127 @@
|
||||
package network
|
||||
|
||||
import (
|
||||
"github.com/duanhf2012/originnet/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
|
||||
}
|
||||
|
||||
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()
|
||||
msgParser.SetMsgLen(server.LenMsgLen, server.MinMsgLen, server.MaxMsgLen)
|
||||
msgParser.SetByteOrder(server.LittleEndian)
|
||||
server.msgParser = msgParser
|
||||
}
|
||||
|
||||
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()
|
||||
}
|
||||
Reference in New Issue
Block a user