Netty连接同时到达的消息

时间:2016-02-26 12:50:09

标签: java tcp byte bytearray netty

我有一个客户端连接到服务器。 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应该有这样的行为吗?我错过了什么吗?

1 个答案:

答案 0 :(得分:3)

TCP是一种基于流的协议,您的应用程序应该从该概念开始工作。 Netty还从网络层接收字节作为流,并将其作为应用程序的工作转换为有用的字节流。

您无法正确转换应用程序可以处理的正确数据块中的传入流字节。

有多种方法可以为字节引入“reframer”:

使每个数据包都是固定长度

如果每个数据包都是固定长度,你可以只读取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的论据是:

  • 长度字段的字节长度