我对如何处理golang TCP客户端上的断开连接有疑问
我具有以下功能,该功能处于连续循环中,并在每个循环中重新连接
func (t *TcpConnector) Connect() {
for {
if t.reconnectAttempt > t.reconnectMaxRetries {
t.onNoReconnect(t.reconnectAttempt)
return
}
if t.reconnectAttempt > 0 {
t.onReconnect()
}
c, err := net.Dial("tcp", t.Url)
if err != nil {
t.AppState.Log.Errorf("Connection to tcp server failed with error : %+v", err)
if t.autoReconnect {
t.reconnectAttempt++
continue
}
return
}
t.Log.Infof("Connection established @ %s", time.Now())
t.Conn = c
defer t.Conn.Close()
var wg sync.WaitGroup
wg.Add(1)
go t.SendHeartbeat()
go t.Write(&wg)
go t.RecieveResponse()
err = t.SendLoginPacket()
if err != nil {
appsetup.MOSLTcpServerLoginFailureAlert(t.AppState, err)
continue
}
wg.Wait()
}
}
我用var wg sync.WaitGroup
阻止了该循环,并在所有等待组完成后继续执行。
SendHeartbeat每30秒将一个数据包写入TCP服务器
func (t *TcpConnector) SendHeartbeat() {
ticker := time.NewTicker(30 * time.Second)
defer ticker.Stop()
for x := range ticker.C {
messageHeader, err := getMessageHeaderInBytes(129, 0, 0, t.AppState.Config.Username)
if err != nil {
t.AppState.Log.Errorf("Error Converting heartbeat request data to bytes: %+v, with seconds: %s", err, x)
return
}
t.DataChannel <- messageHeader
}
}
这通过通道发送字节数据,并被t.Write()
接收
功能。有许多其他功能可以写入此通道,并由Write()
函数
func (t *TcpConnector) Write(wg *sync.WaitGroup) {
for {
select {
case data := <-t.DataChannel:
_, err := t.Conn.Write(data)
if err != nil {
t.AppState.Log.Errorf("Error Sending byte data to TCP server: %+v", err)
t.Conn.Close()
wg.Done()
}
}
}
}
正如您所看到的,我在这里所做的是在出错时-我返回wg.done
,它解除了Connect()
函数的阻塞,并继续连接到服务器。
有时,TCP套接字被关闭,并且Write函数出错。但是由于有多个goroutine并行调用Write()
函数-它们全部出错,并且出现以下错误
panic: sync: negative WaitGroup counter
我理解这是由于Write()
函数在出错时多次调用Wg.Done()
(因为有多个goroutine调用它)引起的。
有没有更好的方法可以解决这个问题?