网络编程之每天学习一点点[day10]-----netty之tcp拆包粘包解决方案二“固定字符串长度”
发布日期:2021-06-30 13:45:24 浏览次数:2 分类:技术文章

本文共 5150 字,大约阅读时间需要 17 分钟。

固定字符串的长度的方式主要是依赖于这个类,先看下jdk中的解释

. . . .FixedLengthFrameDecoder

A decoder that splits the received ByteBufs by the fixed number of bytes. For example, if you received the following four fragmented packets:

+---+----+------+----+ | A | BC | DEFG | HI | +---+----+------+----+
A
FixedLengthFrameDecoder
(3) will decode them into the following three packets with the fixed length:
+-----+-----+-----+ | ABC | DEF | GHI | +-----+-----+-----+

翻译过来就是:

这个类是一个将接收的byteebuf缓冲对象按照固定的字节长度分割的解码器,例如,如果你收到的是以下片段,

+---+----+------+----+ | A | BC | DEFG | HI | +---+----+------+----+

一个按照固定3个字节拆分的解码器将会分割成:

+-----+-----+-----+ | ABC | DEF | GHI | +-----+-----+-----+

我们看下代码:

import io.netty.bootstrap.ServerBootstrap;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.ChannelOption;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioServerSocketChannel;import io.netty.handler.codec.FixedLengthFrameDecoder;import io.netty.handler.codec.string.StringDecoder;public class Server {	public static void main(String[] args) throws Exception{		//1 创建2个线程,一个是负责接收客户端的连接。一个是负责进行数据传输的		EventLoopGroup pGroup = new NioEventLoopGroup();		EventLoopGroup cGroup = new NioEventLoopGroup();				//2 创建服务器辅助类		ServerBootstrap b = new ServerBootstrap();		b.group(pGroup, cGroup)		 .channel(NioServerSocketChannel.class)		 .option(ChannelOption.SO_BACKLOG, 1024)		 .option(ChannelOption.SO_SNDBUF, 32*1024)		 .option(ChannelOption.SO_RCVBUF, 32*1024)		 .childHandler(new ChannelInitializer
() { @Override protected void initChannel(SocketChannel sc) throws Exception { //设置定长字符串接收 sc.pipeline().addLast(new FixedLengthFrameDecoder(5)); //设置字符串形式的解码 sc.pipeline().addLast(new StringDecoder()); sc.pipeline().addLast(new ServerHandler()); } }); //4 绑定连接 ChannelFuture cf = b.bind(8765).sync(); //等待服务器监听端口关闭 cf.channel().closeFuture().sync(); pGroup.shutdownGracefully(); cGroup.shutdownGracefully(); } }

ServerHandler

import io.netty.buffer.Unpooled;import io.netty.channel.ChannelHandlerAdapter;import io.netty.channel.ChannelHandlerContext;public class ServerHandler extends ChannelHandlerAdapter {	@Override	public void channelActive(ChannelHandlerContext ctx) throws Exception {		System.out.println(" server channel active... ");	}	@Override	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {		String request = (String)msg;		System.out.println("Server :" + msg);		String response =  request ;		ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes()));	}	@Override	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {			}	@Override	public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) throws Exception {	}}

Client

import io.netty.bootstrap.Bootstrap;import io.netty.buffer.Unpooled;import io.netty.channel.ChannelFuture;import io.netty.channel.ChannelInitializer;import io.netty.channel.EventLoopGroup;import io.netty.channel.nio.NioEventLoopGroup;import io.netty.channel.socket.SocketChannel;import io.netty.channel.socket.nio.NioSocketChannel;import io.netty.handler.codec.FixedLengthFrameDecoder;import io.netty.handler.codec.string.StringDecoder;public class Client {	public static void main(String[] args) throws Exception {				EventLoopGroup group = new NioEventLoopGroup();				Bootstrap b = new Bootstrap();		b.group(group)		 .channel(NioSocketChannel.class)		 .handler(new ChannelInitializer
() { @Override protected void initChannel(SocketChannel sc) throws Exception { sc.pipeline().addLast(new FixedLengthFrameDecoder(5)); sc.pipeline().addLast(new StringDecoder()); sc.pipeline().addLast(new ClientHandler()); } }); ChannelFuture cf = b.connect("127.0.0.1", 8765).sync(); cf.channel().writeAndFlush(Unpooled.wrappedBuffer("aaaaabbbbb".getBytes())); cf.channel().writeAndFlush(Unpooled.copiedBuffer("ccccccc".getBytes())); //等待客户端端口关闭 cf.channel().closeFuture().sync(); group.shutdownGracefully(); }}

ClientHandler

import io.netty.channel.ChannelHandlerAdapter;import io.netty.channel.ChannelHandlerContext;public class ClientHandler extends ChannelHandlerAdapter{	@Override	public void channelActive(ChannelHandlerContext ctx) throws Exception {		System.out.println("client channel active... ");	}	@Override	public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {		String response = (String)msg;		System.out.println("Client: " + response);	}	@Override	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {	}	@Override	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {	}}

打印:

client

client channel active... Client: aaaaaClient: bbbbbClient: ccccc

Server

server channel active... Server :aaaaaServer :bbbbbServer :ccccc

可以看到客户端发送aaaaabbbbb,被完美分割成aaaaa和bbbbb两部分,但ccccccc含有7个字符,服务器端只能收到ccccc

缺失了2个字符,这是因为使用定长字符串方式只会发送符合长度的字符串,多余的不会被发送,解决办法是可以补齐缺少的字s符,比如给多的cc补三个空格。这样server将会收到:

server channel active... Server :aaaaaServer :bbbbbServer :cccccServer :cc

转载地址:https://jeffsheng.blog.csdn.net/article/details/80809390 如侵犯您的版权,请留言回复原文章的地址,我们会给您删除此文章,给您带来不便请您谅解!

上一篇:网络编程之每天学习一点点[day11]-----netty最佳实践之数据通信
下一篇:Mysql中filesort优化

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月12日 11时24分26秒