在 golang 中的两个不同的 tcp 客户端之间中继数据

Relay data between two different tcp clients in golang

我正在编写一个 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
    }
}

所以每个客户端都有一个协程。并且每个客户端一旦连接到服务器,就会等待读取。服务器然后处理读取的内容。

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

The documentation for net.Conn 明确指出:

Multiple goroutines may invoke methods on a Conn simultaneously.

所以是的,只需写入连接就可以了。您应该注意为每条要发送的消息发出一个 Write 调用。如果您多次调用 Write,您可能会交织来自不同移动设备的消息。这意味着直接调用 Write 而不是通过其他 API (换句话说,不要包装连接)。例如,以下 not 是安全的:

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