【问题标题】:Netty concatenates messages that arrive simultaneouslyNetty 连接同时到达的消息
【发布时间】:2016-02-26 12:50:09
【问题描述】:

我有一个客户端连接到服务器。 TCP 会话中的通信是双向的。如果我尝试同时从服务器向客户端发送多条消息,它们会混合在一个数组中。消息在到达 ByteArrayDecoder 时已经损坏。这是我的管道:

    ChannelPipeline channelPipeline = ch.pipeline();

    channelPipeline.addLast("byteArrayEncoder", new ByteArrayEncoder());
    channelPipeline.addLast("myRequestEncoder", new MyRequestEncoder());
    channelPipeline.addLast("mySecondEncoder", new MySecondEncoder());

    channelPipeline.addLast("byteArraydDecoder", new ByteArrayDecoder());
    channelPipeline.addLast("myResponseDecoder", new MyResponseDecoder());
    channelPipeline.addLast("mySecondDecoder", new MySecondDecoder());

    channelPipeline.addLast("mytHandler", myHandler);

例如,我注意到 ByteArrayDecoder 中的字节数组长度超过 500 而不是 230。并且我看到数组的内容对应于已连接的两个或多个消息。

我只有一个频道。我曾尝试在管道中使用多个 EventExecutorGroup,但这一直在发生,我最终错过了几条入站消息。

但是,使用 1tps 一切似乎都可以正常工作。

netty 应该有这样的行为吗?我错过了什么吗?

【问题讨论】:

  • TCP 应该合并大约在同一时间发送的数据。您需要实现一种协议,该协议可以确定一条消息在哪里结束,下一条消息从哪里开始。

标签: java tcp byte bytearray netty


【解决方案1】:

TCP 是一个基于流的协议,您的应用程序应该从这个概念开始工作。 Netty 还从网络层以流的形式接收字节,应用程序的工作是将字节流转换为有用的东西。

您未能将传入的流式传输字节正确转换为您的应用程序可以处理的正确数据块。

有多种方法可以为字节引入“重构器”:

使每个数据包的长度固定

如果每个数据包都是固定长度的,你可以读取X的字节数,并将其用作简单的成帧解决方案,这使用netty真的很简单:

channelPipeline.addLast("framer", new FixedLengthFrameDecoder(512));

这会将所有传入的字节分成 512 个字节的块。

FixedLengthFrameDecoder 的参数是:

  • 传入数据包的长度

发送前添加数据包长度

除了使每个数据包的大小相同之外,您还可以为数据包添加长度,以便以后拆分数据包。 Netty 还为此提供了有用的实用程序类:

channelPipeline.addLast("framer", new LengthFieldBasedFrameDecoder(Short.MAX_VALUE,0,2,0,2));
channelPipeline.addLast("framer-prepender", new LengthFieldPrepender(2, false));

LengthFieldBasedFrameDecoder 的参数是:

  • 最大帧长度
  • 接收帧长度数据的偏移量
  • 长度字段的字节长度
  • 从收到的消息中删除的字节数

LengthFieldPrepender 的参数是:

  • 长度字段的字节长度

【讨论】:

  • 感谢您的快速回复。一般来说,我对套接字编程一无所知。所以你是说如果我使用帧解码器我不会丢失任何消息我宁愿简单地拆分我的消息然后它们将被正确地发送到下一个解码器?每条消息的前 4 个字节是为其长度保留的,所以我需要使用它。
  • @ampofila 所以现有的消息已经附加了一个长度?在这种情况下,您可以使用 LengthFieldBasedFrameDecoder 来拆分它们而不使用编码器,我相信以下选项可以正常工作:Integer.MAX_VALUE, 0, 4, 0, 0。我还建议您阅读paragraph over stream based decoding in the netty documentation,因为它可以更好地解释如何解决此问题
  • 我仍在测试这个,但现在它不起作用。它只适用于一两个请求,然后我的客户什么也不做。我有 4 种类型的消息,前 3 种具有固定长度,而第 4 种没有。我还注意到阅读这些消息需要更多时间。我的字节序是LITTLE_ENDIAN(我在构造函数中设置的),这有关系吗?
  • @ampofila 我很难在不了解底层协议是如何工作的情况下为您提供帮助,那里有什么样的消息,您有任何文档吗?
  • 没关系,凭借您的原始帖子和良好的睡眠,我设法让它正常工作。我的虚拟服务器在消息头中发送了不正确的长度,因此 LengthFieldBasedFrameDecoder 工作正常。非常感谢。
猜你喜欢
  • 2018-09-15
  • 2012-06-08
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多