我的 Go 服务器上有一个有效的 TCP 套接字设置。我接受传入连接,运行 for 循环并使用 net.Conn.Read 函数读取传入数据。
但这对我来说没有意义。它如何知道已收到完整消息以便继续返回消息大小?
这是我目前的代码:
func (tcpSocket *TCPServer) HandleConnection(conn net.Conn) {
println("Handling connection! ", conn.RemoteAddr().String(), " connected!")
recieveBuffer := make([]byte, 50) // largest message we ever get is 50 bytes
defer func() {
fmt.Println("Closing connection for: ", conn.RemoteAddr().String())
conn.Close()
}()
for {
// how does it know the end of a message vs the start of a new one?
messageSize, err := conn.Read(recieveBuffer)
if err != nil {
return
}
if messageSize > 0 { // update keep alive since we got a message
conn.SetReadDeadline(time.Now().Add(time.Second * 5))
}
}
}
假设我的应用程序发送了一条 6 字节长的消息(可以是任意大小)。 conn.Read
如何知道它何时收到所述消息的结尾然后继续?
我的经验主要在C#,所以Go在这里并不常见。对于我的 C# 应用程序,消息具有第一个字节中包含的消息大小,然后我使用 for 循环读取剩余字节直至消息大小。
但是 Go 中的上述代码似乎获得了完整的消息并继续 - 它如何自动知道我的消息的大小?
我真的很困惑这是怎么发生的,或者当我实际上接近错误时它是否只是运气好。
我所有的消息在第一个字节中都有 header ,说明消息的大小。但似乎我不需要在 Go 服务器上使用它,我是不是误解了它是如何工作的?
最佳答案
TCP 不提供任何消息框架,您可以根据定义的任何协议(protocol)缓冲流和解析消息。
解析 TCP 流时,立即将连接包装在 bufio.Reader
中通常很有用。 ,因为它不仅可以提高阅读效率,还可以为您提供更多有用的方法。您可以如何解析协议(protocol)的示例如下:
buff := make([]byte, 50)
c := bufio.NewReader(conn)
for {
// read a single byte which contains the message length
size, err := c.ReadByte()
if err != nil {
return err
}
// read the full message, or return an error
_, err := io.ReadFull(c, buff[:int(size)])
if err != nil {
return err
}
fmt.Printf("received %x\n", buff[:int(size)])
}
关于sockets - 将 net.Conn.Read 用于持久 TCP 套接字的正确方法是什么,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/47585244/