我使用Netty包在Java中实现了非常简单的Client-Server机器。 当我从客户端向服务器发送大约1000条消息时,Netty创建一个大小为1024的缓冲区并将消息逐个插入缓冲区并发送到ServerHandler(在服务器上),然后将接收到的消息显示在终端上。现在的问题是当缓冲区变满时,缓冲区被发送到服务器并创建一个新的缓冲区,并且消息的剩余字符被插入缓冲区并在缓冲区满时再次发送。这使我的消息字符串有时会被切断并发送到服务器。
例如:
当我将“Hello Netty”从客户端发送到服务器1000次时,缓冲区逐个填充。在特定点,缓冲区已满,显示“Hello”作为内部的最后一部分并发送到服务器。其余部分“Netty”填入新缓冲区并发送到服务器。这就像发送半串。我想消除这个。我认为实现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++;
}
}
ServerHandler
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 HERE14:05:04.572108 = 60 //这需要和上面一起来 STRING,但是CAME是新的弦乐
Netty包中还有一个“UnpooledHeapByteBuf”类。但我不知道如何使用它。请有人帮忙吗?
答案 0 :(得分:2)
由于Tcp mss,套接字可以通过几个数据包发送数据或通过数据包发送多个数据。所以你应该自己拆分或合并数据包。 例如,您可以在数据包标头中添加一个指示数据大小的长度。当然,Netty提供了一些处理程序来解决它。
让我们查看以下代码:
ctx.writeAndFlush(Unpooled.copiedBuffer("abcdefhijk", CharsetUtil.UTF_8));
当您将字节数组发送到另一个时,tcp协议会将其拆分为多个数据包,如下所示:
first packet:"abcdef"
second packet:"hijk"
另一方面,tcp协议还将多个数据合并到一个数据包中:
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
处理程序可以做到这一点。
像这样:
@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()); } });