[TODO]MultiClient
MulitClient:
package plugin import ( "log" "sync" "time" ) type MultiClientConfig struct { FirstAddress string FirstPort int SecondEnable bool SecondAddress string SecondPort int ConnectionType int } const ( CLIENT_NONE = iota CLIENT_FIRST CLIENT_SECOND ) type MultiClientConSate struct { IsConnected bool ClientObject int } const ( DETECT_MODE_NONE = iota DETECT_MODE_ONLY_FIRST DETECT_MODE_FIRST_TO_SECOND DETECT_MODE_SECOND_TO_FIRST ) type MultiClient struct { Config MultiClientConfig ClientConState MultiClientConSate FirstClient TCPClient SecondClient TCPClient Mtx sync.Mutex DetectMode int StopCh chan string wg sync.WaitGroup } func (p *MultiClient) SetClientConState(state *MultiClientConSate) { p.Mtx.Lock() defer p.Mtx.Unlock() p.ClientConState.IsConnected = state.IsConnected p.ClientConState.ClientObject = state.ClientObject log.Printf("set %v,%v", p.ClientConState.IsConnected, p.ClientConState.ClientObject) return } func (p *MultiClient) getClientConState() MultiClientConSate { p.Mtx.Lock() defer p.Mtx.Unlock() return p.ClientConState } func (p *MultiClient) SetConfig(cfg *MultiClientConfig) { p.Mtx.Lock() defer p.Mtx.Unlock() p.Config.FirstAddress = cfg.FirstAddress p.Config.FirstPort = cfg.FirstPort p.Config.SecondEnable = cfg.SecondEnable p.Config.SecondAddress = cfg.SecondAddress p.Config.SecondPort = cfg.SecondPort p.Config.ConnectionType = cfg.ConnectionType // 同步至主、备 firstCfg := TCPClientConfig{ Address: p.Config.FirstAddress, Port: p.Config.FirstPort, ConnectionType: p.Config.ConnectionType, } p.FirstClient.SetConfig(&firstCfg) if p.Config.SecondEnable { secondCfg := TCPClientConfig{ Address: p.Config.SecondAddress, Port: p.Config.SecondPort, ConnectionType: p.Config.ConnectionType, } p.SecondClient.SetConfig(&secondCfg) } } // 外部业务判定网络异常时候,调用接口通知 func (p *MultiClient) NotifyConAbnormal() { //根据现状来判定网络异常的切换逻辑 if !p.isEnableFirstAndSecond() { //仅主配置了 p.FirstClient.Stop() p.SetClientConState(&MultiClientConSate{IsConnected: false, ClientObject: CLIENT_FIRST}) p.setDetectMode(DETECT_MODE_ONLY_FIRST) return } else { currentMultiClientCon := p.getClientConState() log.Printf("notify check %v,%v", currentMultiClientCon.IsConnected, currentMultiClientCon.ClientObject) switch currentMultiClientCon.ClientObject { case CLIENT_FIRST: p.FirstClient.Stop() p.SetClientConState(&MultiClientConSate{IsConnected: false, ClientObject: CLIENT_FIRST}) p.setDetectMode(DETECT_MODE_FIRST_TO_SECOND) case CLIENT_SECOND: p.SecondClient.Stop() p.SetClientConState(&MultiClientConSate{IsConnected: false, ClientObject: CLIENT_SECOND}) p.setDetectMode(DETECT_MODE_SECOND_TO_FIRST) default: return } } return } func (p *MultiClient) setDetectMode(mode int) { p.Mtx.Lock() defer p.Mtx.Unlock() p.DetectMode = mode return } func (p *MultiClient) getDetectMode() int { p.Mtx.Lock() defer p.Mtx.Unlock() return p.DetectMode } func (p *MultiClient) getConfig() MultiClientConfig { p.Mtx.Lock() defer p.Mtx.Unlock() return p.Config } func (p *MultiClient) Start() { log.Printf("MultiClient start enter\n") // 1.启动检测携程 if p.StopCh == nil { p.StopCh = make(chan string, 1) } p.wg.Add(1) go p.handleMultiCenterProc() // 2.启动主连接 p.SetClientConState(&MultiClientConSate{IsConnected: false, ClientObject: CLIENT_FIRST}) if p.FirstClient.Start() { p.SetClientConState(&MultiClientConSate{IsConnected: true, ClientObject: CLIENT_FIRST}) } else { log.Printf("start first fail\n") if p.isEnableFirstAndSecond() { p.setDetectMode(DETECT_MODE_FIRST_TO_SECOND) } else { p.setDetectMode(DETECT_MODE_ONLY_FIRST) } } log.Printf("MultiClient start leave\n") } func (p *MultiClient) Stop() { log.Printf("MultiClient Stop enter!\n") p.StopCh <- "EXIT" close(p.StopCh) p.StopCh = nil p.wg.Wait() log.Printf("proc wait over\n") p.FirstClient.Stop() p.SecondClient.Stop() log.Printf("MultiClient Stop leave\n") } func (p *MultiClient) isEnableFirstAndSecond() bool { if p.Config.SecondEnable && p.Config.SecondAddress != "" { return true } return false } func (p *MultiClient) handleMultiCenterProc() { log.Printf("enter handle Multi proc") defer p.wg.Done() ticker := time.NewTicker(3 * time.Second) defer ticker.Stop() for { if p.StopCh == nil { log.Printf("stop ch closed\n") return } select { case value := <-p.StopCh: log.Printf("ch:%v\n", value) if value == "EXIT" { log.Printf("MAIN stop proc\n") return } case <-ticker.C: p.timerProc() log.Printf("================\n") } } return } func (p *MultiClient) timerProc() { switch p.DetectMode { case DETECT_MODE_NONE: log.Printf("NONE\n") return //当第一连接异常时 case DETECT_MODE_ONLY_FIRST: log.Printf("ONLY_FIRST\n") if p.FirstClient.TestCon() { if p.FirstClient.Start() { p.SetClientConState(&MultiClientConSate{IsConnected: true, ClientObject: CLIENT_FIRST}) p.setDetectMode(DETECT_MODE_NONE) } else { log.Printf("FirstClient test ok but start fail\n") } } else { log.Printf("FirstClient test fail\n") p.SetClientConState(&MultiClientConSate{IsConnected: false, ClientObject: CLIENT_FIRST}) } //当第一连接异常时 case DETECT_MODE_FIRST_TO_SECOND: log.Printf("FIRST_TO_SECOND\n") if p.FirstClient.TestCon() { if p.FirstClient.Start() { p.SetClientConState(&MultiClientConSate{IsConnected: true, ClientObject: CLIENT_FIRST}) p.setDetectMode(DETECT_MODE_NONE) } else { log.Printf("FirstClient test ok but start fail\n") } } else { log.Printf("FirstClient test fail, to test second\n") if p.SecondClient.TestCon() { if p.SecondClient.Start() { p.SetClientConState(&MultiClientConSate{IsConnected: true, ClientObject: CLIENT_SECOND}) p.setDetectMode(DETECT_MODE_SECOND_TO_FIRST) } else { log.Printf("SecondClient test ok but start fail\n") } } else { log.Printf("FirstClient test fail, second test fail\n") } } //当第二连接异常时或正常时 case DETECT_MODE_SECOND_TO_FIRST: log.Printf("SECOND_TO_FIRST\n") if p.FirstClient.TestCon() { if p.FirstClient.Start() { p.SetClientConState(&MultiClientConSate{IsConnected: true, ClientObject: CLIENT_FIRST}) p.setDetectMode(DETECT_MODE_NONE) } else { log.Printf("FirstClient test ok but start fail\n") } } else { // 判断当前第2连接是否处于异常状态 currentConstate := p.getClientConState() if currentConstate.ClientObject == CLIENT_SECOND && currentConstate.IsConnected { return } else { if p.SecondClient.TestCon() { if p.SecondClient.Start() { p.SetClientConState(&MultiClientConSate{IsConnected: true, ClientObject: CLIENT_SECOND}) p.setDetectMode(DETECT_MODE_SECOND_TO_FIRST) } else { log.Printf("SecondClient test ok but start fail\n") } } } } } } func (p *MultiClient) SendAndRecv() { // 根据当前状态决定 }
TCPClient
package plugin import ( "fmt" "log" "net" "sync" "time" ) type TCPClientConfig struct { Address string Port int ConnectionType int } type TCPClient struct { Address string Port int Config TCPClientConfig Mtx sync.Mutex LongCon net.Conn } func (p *TCPClient) SetConfig(cfg *TCPClientConfig) { p.Mtx.Lock() defer p.Mtx.Unlock() p.Config.Address = cfg.Address p.Config.Port = cfg.Port p.Config.ConnectionType = cfg.ConnectionType } func (p *TCPClient) Start() bool { return p.conServer(p.Config.Address, p.Config.Port) } func (p *TCPClient) Stop() bool { if p.LongCon != nil { p.LongCon.Close() } return true } func (p *TCPClient) conServer(addr string, port int) bool { serverAddress := fmt.Sprintf("%s:%d", addr, port) // 尝试创建TCP连接 conn, err := net.DialTimeout("tcp", serverAddress, 3*time.Second) if err != nil { log.Println("连接失败:", err) return false } //defer conn.Close() // 确保连接最后能关闭 p.LongCon = conn log.Println("conServer ok, ", serverAddress) return true } func (p *TCPClient) TestCon() bool { serverAddress := fmt.Sprintf("%s:%d", p.Config.Address, p.Config.Port) // 尝试创建TCP连接 conn, err := net.DialTimeout("tcp", serverAddress, 3*time.Second) if err != nil { log.Println("连接失败:", err) return false } defer conn.Close() // 确保连接最后能关闭 log.Println("TestCon ok, ", serverAddress) return true }
main
func testMultiClient() { fmt.Println("testMultiClient begin") mult := plugin.MultiClient{StopCh: make(chan string, 1)} cfg := plugin.MultiClientConfig{ FirstAddress: "192.168.163.1", FirstPort: 60000, SecondEnable: true, SecondAddress: "192.168.163.1", SecondPort: 60001} mult.SetConfig(&cfg) mult.Start() time.Sleep(30 * time.Second) fmt.Println("test notify abnormal -1") mult.NotifyConAbnormal() fmt.Println("test notify abnormal -1 over") time.Sleep(30 * time.Second) fmt.Println("test notify abnormal -2") mult.NotifyConAbnormal() time.Sleep(30 * time.Second) mult.Stop() fmt.Println("testMultiClient end") } func main() { fmt.Println("hello world") //testMutilGO() //testMutilGOSub() testMultiClient() fmt.Println("main over") }