在Golang中两个不同的TCP客户端之间中继数据

时间:2019-07-03 00:43:00

标签: go tcplistener

我正在编写一个TCP服务器,该服务器同时接受来自移动设备和某些WiFi设备(IOT)的多个连接。建立连接后,需要保持连接,如果没有收到心跳信号,则超时30秒。因此,它类似于以下内容:

// clientsMap map[string] conn

func someFunction() {
    conn, err := s.listener.Accept()
    // I store the conn in clientsMap
    // so I can access it, for brevity not 
    // shown here, then:
    go serve(connn)
}

func serve(conn net.Conn) {
    timeoutDuration := 30 * time.Second
    conn.SetReadDeadline(time.Now().Add(timeoutDuration))
    for {
        msgBuffer := make([]byte, 2048)
        msgBufferLen, err := conn.Read(msgBuffer)
        // do something with the stuff
    }
}

因此,每个客户端只有一个goroutine。每个客户端一旦连接到服务器,就将等待读取。然后,服务器处理读取的内容。

问题是我有时需要从一个客户端读取内容,然后将数据传递给另一个客户端(在移动设备和WiFi设备之间)。我已将连接存储在clientsMap中。所以我可以随时访问。但是,由于每个客户端都由一个goroutine处理,我是否应该通过使用通道将数据从一个客户端传递到另一个客户端?但是,如果goroutine被阻止以等待挂起的读取,如何使它也等待来自通道的数据?还是我应该只从clientsMap获取另一方的连接并写入该连接?

1 个答案:

答案 0 :(得分:1)

The documentation for net.Conn明确指出:

  

多个goroutine可以同时在Conn上调用方法。

是的,可以简单地写入连接。您应该注意,要发送的每个消息都发出一个Write调用。如果您多次呼叫“编写”,则可能会有交错来自不同移动设备的消息的风险。这意味着直接调用而不是通过其他API调用Write(换句话说,不要包装连接)。例如,以下是安全的:

json.NewEncoder(conn).Encode(myValue) // use json.Marshal(myValue) instead
io.Copy(conn, src)                    // use io.ReadAll(src) instead