我有一个非常简单的客户端-服务器机器,使用 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 次重复)
block 引用>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 HERE14: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/