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

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

很简单,直接上代码

import io.netty.bootstrap.ServerBootstrap;import io.netty.buffer.ByteBuf;import io.netty.buffer.Unpooled;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.DelimiterBasedFrameDecoder;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 { //设置特殊分隔符 ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes()); sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, buf)); //设置字符串形式的解码 发来的消息会变成字符串形式 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 :" + request);		//响应的数据也要加上分割符		String response = "服务器响应:" + msg + "$_";		//不能直接返回response字符串,还是得bytebuffer		ctx.writeAndFlush(Unpooled.copiedBuffer(response.getBytes()));	}	@Override	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {			}	@Override	public void exceptionCaught(ChannelHandlerContext ctx, Throwable t) throws Exception {		ctx.close();	}}

Client

import io.netty.bootstrap.Bootstrap;import io.netty.buffer.ByteBuf;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.DelimiterBasedFrameDecoder;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 { //接收服务器发送的数据 以固定分割符来解析 ByteBuf buf = Unpooled.copiedBuffer("$_".getBytes()); sc.pipeline().addLast(new DelimiterBasedFrameDecoder(1024, buf)); 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("bbbb$_".getBytes())); cf.channel().writeAndFlush(Unpooled.wrappedBuffer("cccc$_".getBytes())); //等待客户端端口关闭 cf.channel().closeFuture().sync(); group.shutdownGracefully(); }}

ClientHandler

import io.netty.channel.ChannelHandlerAdapter;import io.netty.channel.ChannelHandlerContext;import io.netty.util.ReferenceCountUtil;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 {		try {			String response = (String)msg;			System.out.println("Client: " + response);		} finally {			ReferenceCountUtil.release(msg);		}	}	@Override	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {	}	@Override	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {		ctx.close();	}}

打印:

Server端:

Client端:

可以看到已经分开了!两次独立的数据请求和响应!

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

上一篇:网络编程之每天学习一点点[day9]-----netty与tomcat的耦合和解耦
下一篇:网络编程之每天学习一点点[day7]-----netty之HelloWorld

发表评论

最新留言

留言是一种美德,欢迎回访!
[***.207.175.100]2024年04月29日 04时13分44秒