<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.81.Final</version>
</dependency>
客户端:
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;
@Slf4j
@Component
public class NettyClientServer {
public void test(String aaa) {
NioEventLoopGroup nioEventLoopGroup = null;
try {
nioEventLoopGroup = new NioEventLoopGroup();
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(nioEventLoopGroup)
.channel(NioSocketChannel.class)
.handler(new MyClientInitializer(aaa));
ChannelFuture channelFuture = bootstrap.connect("X.X.X.X", 8080).sync();
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (nioEventLoopGroup != null) {
nioEventLoopGroup.shutdownGracefully();
}
}
}
}
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;
public class MyClientInitializer extends ChannelInitializer<SocketChannel> {
private final String aaa;
public MyClientInitializer(String aaa) {
this.aaa = aaa;
}
@Override
protected void initChannel(SocketChannel ch) throws Exception {
//声明管道
ChannelPipeline pipeline = ch.pipeline();
//绑定自带的解码器,就是对二进制数据的解析工具,至于解码器构造方法的参数之后详细分析
pipeline.addLast("lengthFieldBasedFrameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
//编码器
pipeline.addLast("lengthFieldPrepender", new LengthFieldPrepender(4));
//由于涉及到服务端和客户端的字符串数据,需要绑定字符串的编解码
pipeline.addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast("stringEncoder", new StringEncoder(CharsetUtil.UTF_8));
//自定义处理器
pipeline.addLast("myClientHandler", new NettyClientHandler(aaa));
}
}
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
import lombok.extern.slf4j.Slf4j;
@Slf4j
/**
* Create by zjg on 2022/9/12
*/
public class NettyClientHandler extends ChannelInboundHandlerAdapter {
private final String aaa;
public NettyClientHandler(String aaa) {
this.aaa = aaa;
}
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(Unpooled.copiedBuffer("qqqq", CharsetUtil.UTF_8));
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
System.out.println("aaaaaaaa------------:" + aaa);
System.out.println("接收到服务端响应:" + msg);
if ("qqqq".equals(msg)) {
ctx.writeAndFlush(Unpooled.copiedBuffer("2222", CharsetUtil.UTF_8));
}
if ("2222".equals(msg)) {
ctx.writeAndFlush(Unpooled.copiedBuffer("3333", CharsetUtil.UTF_8));
}
if ("3333".equals(msg)) {
ctx.writeAndFlush(Unpooled.copiedBuffer("4444", CharsetUtil.UTF_8));
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
cause.printStackTrace();
ctx.close();
}
}
服务端
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Component;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelOption;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import javax.annotation.PostConstruct;
@Slf4j
@Component
public class nettyClientServer {
@PostConstruct
public void createServerSocket() {
NioEventLoopGroup bossGroup = null;
NioEventLoopGroup workGroup = null;
try {
bossGroup = new NioEventLoopGroup();
workGroup = new NioEventLoopGroup();
ServerBootstrap bootstrap = new ServerBootstrap();
bootstrap.group(bossGroup, workGroup)
.channel(NioServerSocketChannel.class)
.option(ChannelOption.SO_BACKLOG, 128)
.childOption(ChannelOption.SO_KEEPALIVE, true)
.childHandler(new MySocketServerInitializer());
ChannelFuture channelFuture = bootstrap.bind(8080).sync();
System.out.println("服务端启动完成!");
channelFuture.channel().closeFuture().sync();
} catch (InterruptedException e) {
e.printStackTrace();
} finally {
if (null != bossGroup) {
bossGroup.shutdownGracefully();
}
if (null != workGroup) {
workGroup.shutdownGracefully();
}
}
}
}
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.LengthFieldBasedFrameDecoder;
import io.netty.handler.codec.LengthFieldPrepender;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;
import io.netty.util.CharsetUtil;
import org.springframework.stereotype.Component;
@Component
public class MySocketServerInitializer extends ChannelInitializer<SocketChannel> {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
//声明管道
ChannelPipeline pipeline = ch.pipeline();
//绑定自带的解码器,就是对二进制数据的解析工具,至于解码器构造方法的参数之后详细分析
pipeline.addLast("lengthFieldBasedFrameDecoder", new LengthFieldBasedFrameDecoder(Integer.MAX_VALUE, 0, 4, 0, 4));
/* 编码器 */
pipeline.addLast("lengthFieldPrepender", new LengthFieldPrepender(4));
//由于涉及到服务端和客户端的字符串数据,需要绑定字符串的编解码
pipeline.addLast("stringDecoder", new StringDecoder(CharsetUtil.UTF_8));
pipeline.addLast("stringEncoder", new StringEncoder(CharsetUtil.UTF_8));
//自定义处理器
pipeline.addLast("mySocketServerHandler", new NettyServerHandler());
}
}
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
public class NettyServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
System.out.println(msg);
ctx.writeAndFlush(msg);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
System.out.println("异常");
cause.printStackTrace();
ctx.close();
}
}