java - 如何在 Netty Java 中创建 HeapBuffer?

标签 java client-server netty

我有一个非常简单的客户端-服务器机器,使用 Netty 包用 Java 实现。 当我从客户端向服务器发送大约 1000 条消息时,Netty 创建一个大小为 1024 的缓冲区,并将消息一一插入到缓冲区中,然后发送到 ServerHandler(在服务器处),后者将收到的消息显示在终端上。现在的问题是,当缓冲区已满时,缓冲区将被发送到服务器,并创建一个新缓冲区,消息的剩余字符将被插入到缓冲区中,并在缓冲区已满时再次发送。这使得我的消息字符串有时被切断并发送到服务器。

例如:

当我从客户端向服务器发送“Hello Netty”1000次时,缓冲区被一一填满。在特定时刻,缓冲区已满,显示“Hello”作为内部的最后一部分,并被发送到服务器。剩余部分“Netty”被填充到新的缓冲区中并发送到服务器。这就像发送 Half 字符串。我想消除这个。我认为实现 Heap Buffer 代替 Unpooled.copiedBuffer(我在下面的代码中实现)可以解决这种情况。难道是这么写的。如果是的话如何在Netty中实现HeapBuffer?

ClientHandler

public void channelActive(ChannelHandlerContext ctx){
      System.out.println("Connected");
      int i=0;
     while(i<10){
        ctx.writeAndFlush(Unpooled.copiedBuffer("8=FIX.4.29=0007935=A49=TTDS68AO56=Min34=152=201704274:05:04.572108=60\n", CharsetUtil.UTF_8)); //created unpooled copiedBuffer. Need to create HeapBuffer
       i++;
    }
}

服务器处理程序

public void channelRead(ChannelHandlerContext ctx, Object msg) {
        ByteBuf in = (ByteBuf) msg;
        System.out.println(in.toString(CharsetUtil.UTF_8));
}

示例输出:(仅显示最多 3 次重复)

8=FIX.4.29=0007935=A49=TTDS68AO56=Min34=152=201704274:05:04.572108=60 8=FIX.4.29=0007935=A49=TTDS68AO56=Min34=152=20170427-14:05:04.572108=60 8=FIX.4.29=0007935=A49=TTDS68AO56=Min34=152=20170427
//HALF STRING CAME HERE

14:05:04.572108=60 //THIS NEED TO COME ALONG WITH THE ABOVE STRING,BUT CAME AS NEW STRING

Netty包中还有一个类“UnpooledHeapByteBuf”。但我不知道如何使用它。请问有人可以帮忙吗?

最佳答案

由于Tcp mss,socket可以通过多个数据包发送一个数据,也可以通过一个数据包发送多个数据。因此,您应该自行拆分或组合数据包。 例如,您可以在数据包 header 中添加指示数据大小的长度。当然,Netty提供了一些处理程序来解决它。

让我们看看下面的代码:

ctx.writeAndFlush(Unpooled.copiedBuffer("abcdefhijk", CharsetUtil.UTF_8));

当你将字节数组发送给对方时,tcp协议(protocol)会将其分成多个数据包,如下所示:

first packet:"abcdef"
second packet:"hijk"

另一方面,tcp 协议(protocol)也将多个数据组合成一个数据包:

ctx.writeAndFlush(Unpooled.copiedBuffer("abcdefhijk", CharsetUtil.UTF_8));
ctx.writeAndFlush(Unpooled.copiedBuffer("abcdefhijk", CharsetUtil.UTF_8));

数据包是:

only packet:"abcdefhijkabcdefhijk"

因此,接收方应该将这些数据包组合成一个数组,或者从数据包中检索一个数组。一种有用的方法是当有人向另一个数据包发送数据时,在每个数据包中添加一个表示数组大小的长度,该长度是数据包的大小大批。 LengthFieldPrepender 处理程序可以做到这一点。数据包如下所示:

* +--------+----------------+
* + 0x000A | "abcdefhijk" |
* +--------+----------------+

接收方应从数据包头中读取长度,长度为0x000A,然后从数据包中读取0x000A字节的数据。LengthFieldBasedFrameDecoder handler 可以做到这一点。

像这样:

@Override public void initChannel(SocketChannel ch) throws Exception{ ch.pipeline()..addLast(new LengthFieldBasedFrameDecoder(204800, 0, 4, 0, 4)) .addLast(new LengthFieldPrepender(4)).addLast(new EchoClientHandler()); } });

@Override public void initChannel(SocketChannel ch) throws Exception { System.out.println("New client connected: " + ch.localAddress()); ch.pipeline().addLast(new LengthFieldBasedFrameDecoder(204800, 0, 4, 0, 4)).addLast(new LengthFieldPrepender(4)).addLast(new FixMessageDecoder()); } });

关于java - 如何在 Netty Java 中创建 HeapBuffer?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/44180034/

相关文章:

java - 让 Java 通过 HTTPS 接受所有证书

java - Java 中带有 Map NullPointerException 的三元运算符

android - 使用客户端服务器架构在 android 中进行序列化

c - 如何防止客户端可以在服务器的任何目录中搜索文件?

java - 跨多个 ServerBootstrap 使用相同的线程池是否安全?

java - FrameDecoder在非单连接情况下不安全吗?

java - Gradle 项目不在我的机器上构建,但在其他人的机器上构建

Java double to long 转换报错之谜

java - java 客户端服务器编程

java - 为什么 Netty 客户端表现得像僵尸?