我正在编写一个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获取另一方的连接并写入该连接?
答案 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