【问题标题】:Parser for TCP buffersTCP 缓冲区的解析器
【发布时间】:2018-11-21 10:06:21
【问题描述】:

我想实现一个协议来在服务器和客户端之间共享数据。 我不知道正确的那个。通过将性能作为主要标准,任何人都可以提出解析数据的最佳协议。

我有一个想法,不要实际名称,但它会像这个

[Header][Message][Header][Message]


标头包含消息的长度,并且标头大小是固定的。 我已经通过执行大量成本更高的连接和子字符串操作来尝试这个。任何人都可以为此建议最佳实现

【问题讨论】:

标签: c++ boost tcp buffer network-protocols


【解决方案1】:

这个问题非常广泛。

关于避免缓冲区/字符串连接的主题,例如在缓冲区序列中,在Boost Asio's "Scatter-Gather" Documentation 中进行了描述

【讨论】:

  • 感谢您的回答。当我确切地知道消息长度时,缓冲区序列将很有帮助。但对于可变消息。变长消息传输有没有具体的标准方法。
  • 感谢您的回答.. 据我所知.. 当消息长度固定时,缓冲区序列会有所帮助...但是对于可变消息,是否有任何方法或标准做法...
  • 您提到了逻辑上适用于发送方的“连接”。在接收端,只需在收到标头后分配/准备缓冲区。您可以使用boost::asio::streambuf 或最新版本中的动态缓冲区概念 (boost.org/doc/libs/1_67_0/doc/html/boost_asio/reference/…)
【解决方案2】:

解析有两种常见的解决方案:

  1. 小消息

将数据接收到缓冲区中,例如64k。然后使用指向该缓冲区的指针来解析标头和消息。由于消息很小,缓冲区中可能有很多消息,只要缓冲区中有数据,您就会再次调用解析器。请注意,缓冲区中的最后一条消息可能会被截断。在这种情况下,您必须保留部分消息并将更多数据读入缓冲区。如果消息接近缓冲区的末尾,则可能需要将其复制到前面。

  1. 大型消息

对于大型消息,首先只阅读标题是有意义的。然后解析头部得到消息大小,为消息分配合适的缓冲区,然后在解析前将整个消息读入其中。

注意:在这两种情况下,您可能希望通过跳过它们或终止连接并出现错误来处理过大的消息。对于第一种情况,消息不能大于缓冲区,并且应该小很多。对于第二种情况,您不想分配例如如果消息应该只有 1MB 左右,则需要 1 GB 来缓冲消息。

对于发送消息,最好先收集所有输出。一个 std::vector 就足够了。或者一根绳子。避免一遍又一遍地将消息复制到更大的缓冲区中。当您拥有所有部分时,最多在最后复制一次。使用 writev() 写入缓冲区列表而不是将它们全部复制到一个缓冲区中也是一种解决方案。

至于最好的协议...什么是最好的?简单地以二进制格式发送数据是最快的,但是当你有不同的架构或版本时会中断。像 google protobuffers 之类的东西可以解决这个问题,但代价是一些速度。这完全取决于您的需求。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-11-13
    • 2019-07-12
    • 2020-09-11
    • 2011-08-22
    • 2013-01-02
    • 2018-04-09
    • 1970-01-01
    相关资源
    最近更新 更多