您的位置:首页 > 其它

Netty使用LineBasedFrameDecoder解决粘包问题

2017-06-01 21:19 651 查看



Netty使用LineBasedFrameDecoder解决粘包问题

问题代码:

服务:
public static void main(String[] args) {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();

try{
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG,1024).childHandler(new TimeServerHandler());
ChannelFuture channelFuture = serverBootstrap.bind(6010).sync();
channelFuture.channel().closeFuture().sync();
}catch (Exception e){
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}

}


handler:
public class TimeServerHandler extends SimpleChannelInboundHandler<Object> {

private int count;

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf = (ByteBuf) msg;
byte[] bytes = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(bytes);
System.out.println(new String(bytes));
//
String str = "hello client**";
System.out.println("receive one msg.count="+ ++count);
ByteBuf whriteByteBuf = Unpooled.copiedBuffer(str.getBytes());
ctx.write(whriteByteBuf);
//        super.channelRead(ctx, msg);
}

@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.flush();
//        super.channelReadComplete(ctx);
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
//        super.exceptionCaught(ctx, cause);
cause.printStackTrace();
ctx.close();
}

@Override
protected void channelRead0(ChannelHandlerContext arg0, Object arg1) throws Exception {
}
}


客户:
public class TimeClient {

public static void main(String[] args) throws Exception {
int port = 6010;
EventLoopGroup workGroup = new NioEventLoopGroup();
try{
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(workGroup).channel(NioSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE,true)
.handler(new ChannelInitializer<SocketChannel>() {

@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new TimeClientHandler());
}
});
ChannelFuture channelFuture = bootstrap.connect("localhost",port).sync();
channelFuture.channel().closeFuture().sync();
}finally {
workGroup.shutdownGracefully();
}
}

}


handler:
public class TimeClientHandler extends SimpleChannelInboundHandler<Object> {

@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
String msg = "hello server";
for(int i = 0; i < 100; i++){
//注意这里每次byteBuf都要重新生成。
ByteBuf byteBuf = Unpooled.buffer(msg.length());
byteBuf.writeBytes(msg.getBytes());
ctx.writeAndFlush(byteBuf);
}
//        super.channelActive(ctx);
}

@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
ByteBuf byteBuf = (ByteBuf) msg;
byte[] bytes = new byte[byteBuf.readableBytes()];
byteBuf.readBytes(bytes);
System.out.println(new String(bytes)+"client888");
//            super.channelRead(ctx, msg);
}

@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
super.channelReadComplete(ctx);
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}

@Override
protected void channelRead0(ChannelHandlerContext arg0, Object arg1) throws Exception {
}
}


服务端运行:



客户端运行:



看到服务端只收到了27条客户端传递过来的数据,应该是有100条才对,可以看出此处发生了TCP粘包。

接下来使用Netty里的LineBasedFrameDecoder来解决此问题。

同样新的服务端:
public class TimeServer {

public static void main(String[] args) {
EventLoopGroup bossGroup = new NioEventLoopGroup();
EventLoopGroup workerGroup = new NioEventLoopGroup();

try{
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup,workerGroup).channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG,1024)
.childHandler(new ChannelInitializer<SocketChannel>() {

@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new LineBasedFrameDecoder(1024));
socketChannel.pipeline().addLast(new TimeServerHandler());
}
});
ChannelFuture channelFuture = serverBootstrap.bind(7601).sync();
channelFuture.channel().closeFuture().sync();
}catch (Exception e){
e.printStackTrace();
} finally {
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}


新的客户端:
public class TimeClient {

public static void main(String[] args) throws Exception {
int port = 7601;
EventLoopGroup workGroup = new NioEventLoopGroup();
try{
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(workGroup).channel(NioSocketChannel.class)
.option(ChannelOption.SO_KEEPALIVE,true)
.handler(new ChannelInitializer<SocketChannel>() {

@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new LineBasedFrameDecoder(1024));
socketChannel.pipeline().addLast(new TimeClientHandler());
}
});//这里就是用ChannelInitializer来处理的。
ChannelFuture channelFuture = bootstrap.connect("localhost",port).sync();
channelFuture.channel().closeFuture().sync();
}finally {
workGroup.shutdownGracefully();
}
}

}


两者的Handler类代码不变。 服务端输出:



客户端输出:



发现TCP粘包问题已经解决。
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: