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

接收可以部分写入的 protobuf 编码消息?

接收可以部分写入的 protobuf 编码消息?

Go
慕森卡 2022-11-23 19:52:11
我正在尝试通过 TCP 在 GoLang 中发送和接收 protobuff 编码的消息,发送方可以write()在操作中途取消,接收方可以正确接收部分消息。请注意,我使用单个 TCP 连接无限发送不同用户定义类型的消息(这不是每个连接消息的情况)为了具体解释我的问题,首先我将介绍如何在没有部分写入的情况下实现发送/接收。在我的程序中,有多种类型的消息,定义在一个.proto文件中。我将解释一种这样的消息类型的机制。message MessageType {  int64 sender = 1;  int64 receiver = 2;  int64 operation = 3;  string message = 4;}然后我使用 Golang Protobuf 插件生成存根。然后在发送方,下面是我发送的方式。func send(w *bufio.Writer, code uint8, oriMsg MessageType) {    err := w.WriteByte(code)    data, err := proto.Marshal(oriMsg)    lengthWritten := len(data)    var b [8]byte    bs := b[:8]    binary.LittleEndian.PutUint64(bs, uint64(lengthWritten))    _, err = w.Write(bs)    _, err = w.Write(data)    w.flush()}然后在receiver端,下面是我的接收方式。reader *bufio.Readerfor true {        if msgType, err = reader.ReadByte(); err != nil {            panic()        }        if msgType == 1 || msgType == 2{            var b [8]byte            bs := b[:8]            _, err := io.ReadFull(reader, bs)             numBytes := binary.LittleEndian.Uint64(bs)            data := make([]byte, numBytes)            length, err := io.ReadFull(reader, data)             msg *MessageType = new(GenericConsensus) // an empty message             err = proto.Unmarshal(data[:length], msg)             // do something with the message                     } else {            // unknown message type handler        }    }现在我的问题是,如果发件人在中间中止他的写入怎么办:更具体地说,情况 1:如果发送方写入消息类型字节,然后中止怎么办?在这种情况下,接收方将读取消息类型字节,并等待接收 8 字节的消息长度,但发送方不发送它。情况 2:这是情况 1 的扩展版本,其中发送方首先仅发送消息类型字节,中止发送消息长度和编组消息,然后发送下一条消息:类型字节、长度和编码消息。现在在接收方,一切都出错了,因为违反了消息的顺序(类型、长度和编码消息)。所以我的问题是,如何修改接收方,使其在发送方违反预先约定的 type:length:encoded-message 顺序的情况下仍能继续运行?
查看完整描述

1 回答

?
慕少森

TA贡献2019条经验 获得超9个赞

为什么发件人会中止一条消息,然后发送另一条消息?你的意思是它是一个完全拜占庭式的发件人?还是您正在准备进行模糊测试?

如果您的 API 合同规定发送方始终需要发送正确的消息,那么接收方可以简单地忽略错误消息,甚至可以在发现违反 API 合同的情况下关闭连接。

如果你真的需要它,这里有一些关于如何让它工作的想法:

  • 从一个独特的序言开始——但是你必须确保这个序言永远不会出现在数据中

  • 在将消息发送到解码器之前向消息添加校验和。所以完整的数据包将是[msg_type : msg_len : msg : chksum ]:这允许接收方检查它是正确的消息还是格式错误的消息。

此外,就目前的代码而言,发送最大 64 位的大小很容易导致崩溃。所以你还应该检查大小是否在一个有用的范围内。我会将其限制为 32 位...


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

添加回答

举报

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