使用原始 tcp 时确保完整消息传递的好方法是什么?
What's a good way to ensure delivery of an entire message when using raw tcp?
假设我有一个应用程序,我想在后端使用原始 tcp,以便我可以在不同服务之间进行双向通信。在此应用程序中,我想发送一个由 json 对象组成的有效负载,当发送 json 数据时,每隔几条消息,它就会被切断,然后将其余部分聚集到下一个响应中。由于用于从 http 升级的时间,我不想使用像 websockets 这样的东西。什么是确保 json 对象从一个节点发出并作为 whole json 对象从另一个节点读取的好方法(希望是最好的方法) ?
我知道设置大小的发送和接收缓冲区以及针对心跳信号的消息是经验法则,但我可以举个例子吗?最好是 Javascript(node 的 net stdlib)或 Golang(它是 net stdlib),因为这些是我最精通的语言,尽管我真的不在乎它最终是用什么语言完成的。
(我知道有几个问题询问有关确保使用 tcp 传递消息的类似问题,但 none 询问了我找到的示例)
我知道tcp是一个流。我只是问一种方法来确保在将特定的 json 对象写入此流时,如何确保在另一端获得相同的 json 对象,如 "send json object X from node a, ok node b received that same object X"
您不需要检测信号或固定大小的邮件来确认送达。如果您需要确保交付,则需要应用程序级别的确认。如果您需要确保 正确 邮件的传送,您需要包含一个唯一的邮件 ID 以进行确认。如果您需要确保消息未被更改,则需要包含校验和或 MAC.
听起来您在消息框架方面遇到了问题。虽然有很多方法来构建消息(简单的长度前缀、type-length-value、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)
}
}
假设我有一个应用程序,我想在后端使用原始 tcp,以便我可以在不同服务之间进行双向通信。在此应用程序中,我想发送一个由 json 对象组成的有效负载,当发送 json 数据时,每隔几条消息,它就会被切断,然后将其余部分聚集到下一个响应中。由于用于从 http 升级的时间,我不想使用像 websockets 这样的东西。什么是确保 json 对象从一个节点发出并作为 whole json 对象从另一个节点读取的好方法(希望是最好的方法) ?
我知道设置大小的发送和接收缓冲区以及针对心跳信号的消息是经验法则,但我可以举个例子吗?最好是 Javascript(node 的 net stdlib)或 Golang(它是 net stdlib),因为这些是我最精通的语言,尽管我真的不在乎它最终是用什么语言完成的。
(我知道有几个问题询问有关确保使用 tcp 传递消息的类似问题,但 none 询问了我找到的示例)
我知道tcp是一个流。我只是问一种方法来确保在将特定的 json 对象写入此流时,如何确保在另一端获得相同的 json 对象,如 "send json object X from node a, ok node b received that same object X"
您不需要检测信号或固定大小的邮件来确认送达。如果您需要确保交付,则需要应用程序级别的确认。如果您需要确保 正确 邮件的传送,您需要包含一个唯一的邮件 ID 以进行确认。如果您需要确保消息未被更改,则需要包含校验和或 MAC.
听起来您在消息框架方面遇到了问题。虽然有很多方法来构建消息(简单的长度前缀、type-length-value、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)
}
}