mirror of
https://github.com/duanhf2012/origin.git
synced 2026-02-03 22:45:13 +08:00
160 lines
3.3 KiB
Go
160 lines
3.3 KiB
Go
package network
|
|
|
|
import (
|
|
"github.com/duanhf2012/origin/v2/log"
|
|
"net"
|
|
"sync"
|
|
"time"
|
|
)
|
|
|
|
type TCPClient struct {
|
|
sync.Mutex
|
|
Addr string
|
|
ConnNum int
|
|
ConnectInterval time.Duration
|
|
PendingWriteNum int
|
|
ReadDeadline time.Duration
|
|
WriteDeadline time.Duration
|
|
AutoReconnect bool
|
|
NewAgent func(*TCPConn) Agent
|
|
cons ConnSet
|
|
wg sync.WaitGroup
|
|
closeFlag bool
|
|
|
|
// msg parser
|
|
MsgParser
|
|
}
|
|
|
|
func (client *TCPClient) Start() {
|
|
client.init()
|
|
|
|
for i := 0; i < client.ConnNum; i++ {
|
|
client.wg.Add(1)
|
|
go client.connect()
|
|
}
|
|
}
|
|
|
|
func (client *TCPClient) init() {
|
|
client.Lock()
|
|
defer client.Unlock()
|
|
|
|
if client.ConnNum <= 0 {
|
|
client.ConnNum = 1
|
|
log.Info("invalid ConnNum",log.Int("reset", client.ConnNum))
|
|
}
|
|
if client.ConnectInterval <= 0 {
|
|
client.ConnectInterval = 3 * time.Second
|
|
log.Info("invalid ConnectInterval",log.Duration("reset", client.ConnectInterval))
|
|
}
|
|
if client.PendingWriteNum <= 0 {
|
|
client.PendingWriteNum = 1000
|
|
log.Info("invalid PendingWriteNum",log.Int("reset",client.PendingWriteNum))
|
|
}
|
|
if client.ReadDeadline == 0 {
|
|
client.ReadDeadline = 15*time.Second
|
|
log.Info("invalid ReadDeadline",log.Int64("reset", int64(client.ReadDeadline.Seconds())))
|
|
}
|
|
if client.WriteDeadline == 0 {
|
|
client.WriteDeadline = 15*time.Second
|
|
log.Info("invalid WriteDeadline",log.Int64("reset", int64(client.WriteDeadline.Seconds())))
|
|
}
|
|
if client.NewAgent == nil {
|
|
log.Fatal("NewAgent must not be nil")
|
|
}
|
|
if client.cons != nil {
|
|
log.Fatal("client is running")
|
|
}
|
|
|
|
if client.MinMsgLen == 0 {
|
|
client.MinMsgLen = Default_MinMsgLen
|
|
}
|
|
if client.MaxMsgLen == 0 {
|
|
client.MaxMsgLen = Default_MaxMsgLen
|
|
}
|
|
if client.LenMsgLen ==0 {
|
|
client.LenMsgLen = Default_LenMsgLen
|
|
}
|
|
maxMsgLen := client.MsgParser.getMaxMsgLen(client.LenMsgLen)
|
|
if client.MaxMsgLen > maxMsgLen {
|
|
client.MaxMsgLen = maxMsgLen
|
|
log.Info("invalid MaxMsgLen",log.Uint32("reset", maxMsgLen))
|
|
}
|
|
|
|
client.cons = make(ConnSet)
|
|
client.closeFlag = false
|
|
client.MsgParser.init()
|
|
}
|
|
|
|
func (client *TCPClient) GetCloseFlag() bool{
|
|
client.Lock()
|
|
defer client.Unlock()
|
|
|
|
return client.closeFlag
|
|
}
|
|
|
|
func (client *TCPClient) dial() net.Conn {
|
|
for {
|
|
conn, err := net.Dial("tcp", client.Addr)
|
|
if client.closeFlag {
|
|
return conn
|
|
} else if err == nil && conn != nil {
|
|
conn.(*net.TCPConn).SetNoDelay(true)
|
|
return conn
|
|
}
|
|
|
|
log.Warning("connect error ",log.String("error",err.Error()), log.String("Addr",client.Addr))
|
|
time.Sleep(client.ConnectInterval)
|
|
continue
|
|
}
|
|
}
|
|
|
|
func (client *TCPClient) connect() {
|
|
defer client.wg.Done()
|
|
|
|
reconnect:
|
|
conn := client.dial()
|
|
if conn == nil {
|
|
return
|
|
}
|
|
|
|
client.Lock()
|
|
if client.closeFlag {
|
|
client.Unlock()
|
|
conn.Close()
|
|
return
|
|
}
|
|
client.cons[conn] = struct{}{}
|
|
client.Unlock()
|
|
|
|
tcpConn := newTCPConn(conn, client.PendingWriteNum, &client.MsgParser,client.WriteDeadline)
|
|
agent := client.NewAgent(tcpConn)
|
|
agent.Run()
|
|
|
|
// cleanup
|
|
tcpConn.Close()
|
|
client.Lock()
|
|
delete(client.cons, conn)
|
|
client.Unlock()
|
|
agent.OnClose()
|
|
|
|
if client.AutoReconnect {
|
|
time.Sleep(client.ConnectInterval)
|
|
goto reconnect
|
|
}
|
|
}
|
|
|
|
func (client *TCPClient) Close(waitDone bool) {
|
|
client.Lock()
|
|
client.closeFlag = true
|
|
for conn := range client.cons {
|
|
conn.Close()
|
|
}
|
|
client.cons = nil
|
|
client.Unlock()
|
|
|
|
if waitDone == true{
|
|
client.wg.Wait()
|
|
}
|
|
}
|
|
|