新增依賴
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.110.Final</version>
</dependency>
<dependency>
<groupId>ch.qos.logback</groupId>
<artifactId>logback-classic</artifactId>
<version>1.2.12</version>
</dependency>
服務端
【NettyServerTest.java】
@Slf4j
public class NettyServerTest
{
public static void main(String[] args) throws Exception
{
EventLoopGroup bossGroup = new NioEventLoopGroup(1);
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
// 建立伺服器端的啟動物件,配置引數
ServerBootstrap serverBootstrap = new ServerBootstrap();
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new MyServerChannelInitializer());
// 繫結埠,同步等待成功
ChannelFuture channelFuture = serverBootstrap.bind(8080).sync();
// 等待服務端監聽埠關閉
channelFuture.channel().closeFuture().sync();
log.info("end!!!!!!!!!!!!!!!!!!!!!!");
} finally {
// 優雅退出,釋放執行緒池資源
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
}
【MyServerChannelInitializer.java】
public class MyServerChannelInitializer extends ChannelInitializer<SocketChannel>
{
@Override
public void initChannel(SocketChannel socketChannel) {
socketChannel.pipeline().addLast(new StringDecoder());
socketChannel.pipeline().addLast(new StringEncoder());
socketChannel.pipeline().addLast(new MyServerChannelInBoundHandler());
}
}
這裡要注意pipeline裡面的Handler的順序,【StringEncoder】一定要放到【MyServerChannelInBoundHandler】的前面,因為【MyServerChannelInBoundHandler】是傳送字串資料出去,字型串要經過【StringEncoder】編碼成位元組碼之後才能成功傳送出去。
【MyServerChannelInBoundHandler.java】
@Slf4j
public class MyServerChannelInBoundHandler extends SimpleChannelInboundHandler<String>
{
@Override
public void channelActive(ChannelHandlerContext ctx) {
log.info("MyChannelInBoundHandler.channelActive[" + ctx.channel().remoteAddress() + "]: ");
ctx.writeAndFlush("I'm server, thanks for connected!\r\n");
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
log.info("MyChannelInBoundHandler.channelReadComplete[" + ctx.channel().remoteAddress() + "]");
super.channelReadComplete(ctx);
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, String msg) {
log.info("MyChannelInBoundHandler.channelRead0[" + ctx.channel().remoteAddress() + "]:" + msg);
ctx.writeAndFlush(msg);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) {
log.info("MyChannelInBoundHandler.channelInactive[" + ctx.channel().remoteAddress() + "]: ");
}
}
客戶端
【NettyClientTest.java】
@Slf4j
public class NettyClientTest
{
public static void main(String[] args) throws Exception
{
EventLoopGroup workerEventLoopGroup = new NioEventLoopGroup();
try {
Bootstrap bootstrap = new Bootstrap();
bootstrap.group(workerEventLoopGroup)
.channel(NioSocketChannel.class)
.handler(new MyClientChannelInitializer());
ChannelFuture future = bootstrap.connect("localhost", 8080).sync();
future.channel().closeFuture().sync();
} finally {
// 6. 關閉工作執行緒組
workerEventLoopGroup.shutdownGracefully();
}
}
}
【MyClientChannelInitializer.java】
public class MyClientChannelInitializer extends ChannelInitializer<SocketChannel>
{
@Override
protected void initChannel(SocketChannel socketChannel) throws Exception {
socketChannel.pipeline().addLast(new StringDecoder()); // 新增字串解碼器
socketChannel.pipeline().addLast(new StringEncoder()); // 新增字串編碼器
socketChannel.pipeline().addLast(new MyClientInBoundHandler()); // 自定義的客戶端處理器
}
}
注意【StringEncoder】和【MyClientInBoundHandler】的順序要正確
【MyClientInBoundHandler.java】
@Slf4j
public class MyClientInBoundHandler extends ChannelInboundHandlerAdapter
{
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
log.info("channelActive[" + ctx.channel().remoteAddress() + "]");
ctx.writeAndFlush("Hello, Server, I'm client!\r\n");
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
log.info("channelReadComplete[" + ctx.channel().remoteAddress() + "]: " );
super.channelReadComplete(ctx);
}
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
log.info("channelRead[" + ctx.channel().remoteAddress() + "]: " + msg);
super.channelRead(ctx, msg);
}
@Override
public void channelInactive(ChannelHandlerContext ctx) throws Exception {
log.info("channelInactive[" + ctx.channel().remoteAddress() + "]");
super.channelInactive(ctx);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
log.error("exceptionCaught", cause);
ctx.close();
}
}