什么是使用net.conn.Read用于持久性TCP插座的正确方法



我在GO服务器上有一个工作的TCP套接字设置。我接受传入的连接,运行循环A并使用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 loop来读取剩余的字节至消息大小。

但是,GO中的上述代码似乎收到了完整的消息并继续 - 它有些自动知道我的消息的大小?

我真的很困惑这种情况是如何发生的,或者当我真正接近错误时,它只是在运气中工作。

我所有的消息都在第一个字节中陈述了消息的大小。但是看来我不需要在GO服务器上,我是否误解了这是如何工作的?

tcp不提供任何消息框架,取决于您可以根据您定义的任何协议来缓冲流并解析消息。

解析TCP流时,立即将连接包裹在bufio.Reader中通常很有用,因为它不仅可以使阅读效率更有效,而且还可以为您提供更有用的方法。您如何解析协议的一个示例是:

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 %xn", buff[:int(size)])
}

最新更新