Golang TCP客户端服务器实现

时间:2019-07-18 13:41:48

标签: go

我对如何处理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调用它)引起的。

有没有更好的方法可以解决这个问题?

0 个答案:

没有答案