使用原始 tcp 时确保传递整个消息的好方法是什么?

假设我有一个在后端的应用程序,我想使用原始 tcp 以便我可以在不同的服务之间进行双向通信。在这个应用程序中,我想发送一个由 json 对象组成的有效负载,当发送 json 数据时,每隔几条消息,它就会被截断,其余的将聚集到下一个响应中。由于用于从 http 升级的时间,我不想使用诸如 websockets 之类的东西。什么是确保该 json 对象将从一个节点作为整个json 对象从另一个节点读取的好(并且希望是最好的)方法?

我知道发送和接收设置大小的缓冲区和用于 heartbeet 的消息是经验法则,但我可以看一个例子吗?最好使用 Javascript(节点的 net stdlib)或 Golang(它是 net stdlib),因为这些是我最精通的语言,尽管我并不真正关心它最终是用什么语言完成的。

(我知道有一些问题在询问有关确保使用 tcp 传递消息的类似问题,但没有人要求提供我发现的示例)

我知道 tcp 是一个流。我只是要求一种方法来确保在将特定的 json 对象写入此流时,如何确保在另一端获得相同的 json 对象,如“从节点 a 发送 json 对象 X,好的节点 b”收到同一个对象X"


智慧大石
浏览 187回答 1
1回答

繁星coding

您不需要心跳或固定大小的消息来确认交付。如果您需要确保交付,则需要应用程序级别的确认。如果您需要确保传递正确的消息,则需要包含一个唯一的消息 ID 以进行确认。如果您需要确保消息未更改,则需要包含校验和或 MAC。在这里,您似乎在消息框架方面遇到了问题。虽然有很多方法来构建您的消息(简单的长度前缀、类型长度值、HTTP/1.1 等),但一个简单的解决方案是使用内置的json.Encoder和json.Decoder。示例客户端,每秒发送一条“PING”消息:type Message struct {    Payload string}func sendMessages(c net.Conn) {    message := Message{}    encoder := json.NewEncoder(c)    for i := 0; ; i++ {        message.Payload = fmt.Sprintf("PING %d", i)        err := encoder.Encode(message)        if err != nil {            log.Fatal(err)        }        time.Sleep(time.Second)    }}示例服务器:type Message struct {    Payload string}func receiveMessages(c net.Conn) {    m := Message{}    decoder := json.NewDecoder(c)    for {        err := decoder.Decode(&m)        if err != nil {            log.Fatal(err)        }        fmt.Printf("Received: %#v\n", m)    }}
打开App,查看更多内容
随时随地看视频慕课网APP

相关分类

Go