这里写自定义目录标题
使用分隔符解码器
服务端
import io.netty.bootstrap.*;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
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 void bind(int port) {
//1、创建线程池,服务端创建连个线程池
NioEventLoopGroup boosGroup = new NioEventLoopGroup();
NioEventLoopGroup workerGroup = new NioEventLoopGroup();
//2、创建服务端启动对象
ServerBootstrap bootstrap = new ServerBootstrap();
//3、配置启动对象
bootstrap.group(boosGroup, workerGroup) //4、添加线程池
.channel(NioServerSocketChannel.class) //5、使用 NioServerSocketChannel 作为服务器 端通道实现
.option(ChannelOption
.SO_BACKLOG, 128) //6、设置线程队列中等待连接的个数
.childOption(ChannelOption.SO_KEEPALIVE, true) //7、保持活动状态连接
.childHandler(new ChannelInitializer<SocketChannel>() { //8、创建一个通道初始化对象
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();//9、往 Pipeline 链中添加自定义的业务 处理 handler
ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes());
//10、添加分隔符解码器(指定$_为分隔符,如果超过1024个字迹未找到分隔符将会报错)
pipeline.addLast(new DelimiterBasedFrameDecoder(1024, delimiter));
//11、添加字符转解码器,将消息转为字符串
pipeline.addLast(new StringDecoder());
//12、添加自定义的处理类
pipeline.addLast(new EchoServerHandler());
}
});
try {
//13、启动服务器端并绑定端口,等待接受客户端连接(bind为非阻塞,sync为阻塞式的)
ChannelFuture channelFuture = bootstrap.bind(port).sync();
System.out.println("------Server is ready------");
//14、关闭通道(closeFuture为非阻塞,sync为阻塞式的)
channelFuture.channel().closeFuture().sync();
} catch (Exception e) {
e.printStackTrace();
System.out.println("------Chat Server is close------");
} finally {
boosGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) {
Server chatServer = new Server();
chatServer.bind(9999);
}
class EchoServerHandler extends SimpleChannelInboundHandler<String>{
int count = 0;
protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {
String body = (String)msg;
System.out.println("This is "+ ++count + "times receive client : ["+ body + "]");
body += "$_";
ByteBuf echo = Unpooled.copiedBuffer(body.getBytes());
ctx.writeAndFlush(echo);
}
public void exceptionCaught(ChannelHandlerContext ctx,Throwable cause){
cause.printStackTrace();
ctx.close();
}
}
}
客户端
import io.netty.bootstrap.Bootstrap;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.*;
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 void connect(int port,String host){
//初始化线程池
NioEventLoopGroup group = new NioEventLoopGroup();
//创建启动器
Bootstrap bootstrap = new Bootstrap();
//配置启动器
bootstrap.group(group)
.channel(NioSocketChannel.class)
.option(ChannelOption.TCP_NODELAY,true)
.handler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
ChannelPipeline pipeline = socketChannel.pipeline();//9、往 Pipeline 链中添加自定义的业务 处理 handler
ByteBuf delimiter = Unpooled.copiedBuffer("$_".getBytes());
//10、添加分隔符解码器(指定$_为分隔符,如果超过1024个字迹未找到分隔符将会报错)
pipeline.addLast(new DelimiterBasedFrameDecoder(1024, delimiter));
//11、添加字符转解码器,将消息转为字符串
pipeline.addLast(new StringDecoder());
//添加自定义的处理类
pipeline.addLast(new EchoClientHandler());
}
});
try{
ChannelFuture channelFuture = bootstrap.connect(host, port).sync();
channelFuture.channel().closeFuture().sync();
}catch (Exception e){
System.out.println("连接异常");
}
}
public static void main(String[] args) {
new Client().connect(9999,"127.0.0.1");
}
class EchoClientHandler extends SimpleChannelInboundHandler<String>{
private int counter;
static final String ECHO_REQ = "Hi,Ni hao,Welcome to Netty.$_";
protected void channelRead0(ChannelHandlerContext channelHandlerContext, String o) throws Exception {
System.out.println(++counter+":"+o);
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
for(int i=0;i<10;i++){
ctx.writeAndFlush(Unpooled.copiedBuffer(ECHO_REQ.getBytes()));
}
}
}
}
定长解码器:
//每次按照20个字符进行解码,如果是半包消息,会缓存半包消息并等待下一个半包进行拼包
pipeline.addLast(new FixedLengthFrameDecoder(20));