为了账号安全,请及时绑定邮箱和手机立即绑定

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

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

Go
智慧大石 2021-11-08 10:03:00
假设我有一个在后端的应用程序,我想使用原始 tcp 以便我可以在不同的服务之间进行双向通信。在这个应用程序中,我想发送一个由 json 对象组成的有效负载,当发送 json 数据时,每隔几条消息,它就会被截断,其余的将聚集到下一个响应中。由于用于从 http 升级的时间,我不想使用诸如 websockets 之类的东西。什么是确保该 json 对象将从一个节点作为整个json 对象从另一个节点读取的好(并且希望是最好的)方法?我知道发送和接收设置大小的缓冲区和用于 heartbeet 的消息是经验法则,但我可以看一个例子吗?最好使用 Javascript(节点的 net stdlib)或 Golang(它是 net stdlib),因为这些是我最精通的语言,尽管我并不真正关心它最终是用什么语言完成的。(我知道有一些问题在询问有关确保使用 tcp 传递消息的类似问题,但没有人要求提供我发现的示例)我知道 tcp 是一个流。我只是要求一种方法来确保在将特定的 json 对象写入此流时,如何确保在另一端获得相同的 json 对象,如“从节点 a 发送 json 对象 X,好的节点 b”收到同一个对象X"
查看完整描述

1 回答

?
繁星coding

TA贡献1797条经验 获得超4个赞

您不需要心跳或固定大小的消息来确认交付。如果您需要确保交付,则需要应用程序级别的确认。如果您需要确保传递正确的消息,则需要包含一个唯一的消息 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)

    }

}


查看完整回答
反对 回复 2021-11-08
  • 1 回答
  • 0 关注
  • 186 浏览
慕课专栏
更多

添加回答

举报

0/150
提交
取消
意见反馈 帮助中心 APP下载
官方微信