<!-- netty-->
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.1.6.Final</version>
</dependency>
2.EchoServerHandler
package com.hzm.myproject.netty.echo;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelFutureListener;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
import io.netty.util.CharsetUtil;
/**
* @Author:huangzhimin
* @Date:2020/6/8
* @描述:echo 服务端 处理消息的业务逻辑
*
**/
@ChannelHandler.Sharable //@Sharable 标识这类的实例之间可以在 channel 里面共享
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
/**
* 每个信息入站都会被调用
* @param ctx
* @param msg
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf in = (ByteBuf) msg;
//将日志消息是输出到控制台
System.out.println("Server received: " + in.toString(CharsetUtil.UTF_8));
//将所接收的消息返回给发送者。注意,这还没有冲刷数据
ctx.write(in);
}
/**
* 通知处理器最后的 channelRead() 是当前批处理中的最后一条消息时调用
* @param ctx
* @throws Exception
*/
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
// 冲刷所有待审消息到远程节点。关闭通道后,操作完成
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER).addListener(ChannelFutureListener.CLOSE);
}
/**
* 读操作时捕获到异常时调用
* @param ctx
* @param cause
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace(); //5 打印异常堆栈跟踪
ctx.close(); //6 关闭通道
}
}
3.EchoServer
package com.hzm.myproject.netty.echo;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.Channel;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
import java.net.InetSocketAddress;
/**
* @Author:huangzhimin
* @Date:2020/6/8
* @描述:引导服务
* 1.监听和接收进来的连接请求
* 2.配置 Channel 来通知一个关于入站消息的 EchoServerHandler 实例
**/
public class EchoServer {
private final int port;
public EchoServer(int port) {
this.port = port;
}
public static void main(String[] args) throws Exception {
// if (args.length != 1) {
// System.err.println("Usage: " + EchoServer.class.getSimpleName() + " ");
// return;
// }
//设置端口值(抛出一个 NumberFormatException 如果该端口参数的格式不正确)
int port = Integer.parseInt("9999");
//呼叫服务器的 start() 方法
new EchoServer(port).start();
}
public void start() throws Exception {
//创建 EventLoopGroup
NioEventLoopGroup group = new NioEventLoopGroup(); //3
try {
ServerBootstrap bootstrap = new ServerBootstrap();
//创建 ServerBootstrap
bootstrap.group(group)
//指定使用 NIO 的传输 Channel
.channel(NioServerSocketChannel.class)
//设置 socket 地址使用所选的端口
.localAddress(new InetSocketAddress(port))
//添加 EchoServerHandler 到 Channel 的 ChannelPipeline
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new EchoServerHandler());
}
});
//绑定的服务器;sync 等待服务器关闭
ChannelFuture future = bootstrap.bind().sync();
System.out.println(EchoServer.class.getName() + " started and listen on " + future.channel().localAddress());
//关闭 channel 和 块,直到它被关闭
future.channel().closeFuture().sync();
} finally {
//关闭 EventLoopGroup,释放所有资源
group.shutdownGracefully().sync();
}
}
}
4.EchoClientHandler
package com.hzm.myproject.netty.echo;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandler;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;
import io.netty.util.CharsetUtil;
/**
* @Author:huangzhimin
* @Date:2020/6/8
* @描述:
* 连接服务器
* 发送信息
* 发送的每个信息,等待和接收从服务器返回的同样的信息
* 关闭连接
**/
@ChannelHandler.Sharable //@Sharable 标记这个类的实例可以在 channel 里共享
public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
/**
* 服务器的连接被建立后调用
* @param ctx
*/
@Override
public void channelActive(ChannelHandlerContext ctx) {
//当被通知该 channel 是活动的时候就发送信息
ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks!---hzm", CharsetUtil.UTF_8));
}
/**
* 数据后从服务器接收到调用
* @param ctx
* @param in
*/
@Override
public void channelRead0(ChannelHandlerContext ctx, ByteBuf in) {
//记录接收到的消息
System.out.println("Client received: " + in.toString(CharsetUtil.UTF_8));
}
/**
* 捕获一个异常时调用
* @param ctx
* @param cause
*/
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
//记录日志错误并关闭 channel
cause.printStackTrace();
ctx.close();
}
}
5.EchoClient
package com.hzm.myproject.netty.echo;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
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 java.net.InetSocketAddress;
/**
* @Author:huangzhimin
* @Date:2020/6/8
* @描述:引导客户端
**/
public class EchoClient {
private final String host;
private final int port;
public EchoClient(String host, int port) {
this.host = host;
this.port = port;
}
public void start() throws Exception {
EventLoopGroup group = new NioEventLoopGroup();
try {
//1创建 Bootstrap
Bootstrap bootstrap = new Bootstrap();
//2指定 EventLoopGroup 来处理客户端事件。由于我们使用 NIO 传输,所以用到了 NioEventLoopGroup 的实现
bootstrap.group(group)
//3使用的 channel 类型是一个用于 NIO 传输
.channel(NioSocketChannel.class)
//4设置服务器的 InetSocketAddress
.remoteAddress(new InetSocketAddress(host, port))
//5当建立一个连接和一个新的通道时,创建添加到 EchoClientHandler 实例 到 channel pipeline
.handler(new ChannelInitializer<SocketChannel>() {
@Override
public void initChannel(SocketChannel ch) throws Exception {
ch.pipeline().addLast(new EchoClientHandler());
}
});
//6 连接到远程;等待连接完成
ChannelFuture future = bootstrap.connect().sync();
//7 阻塞直到 Channel 关闭
future.channel().closeFuture().sync();
} finally {
//8调用 shutdownGracefully() 来关闭线程池和释放所有资源
group.shutdownGracefully().sync();
}
}
public static void main(String[] args) throws Exception {
// if (args.length != 2) {
// System.err.println("Usage: " + EchoClient.class.getSimpleName() + " ");
// return;
// }
final String host = "0:0:0:0:0:0:0:0"; //服务器的路径
final int port = Integer.parseInt("9999");//服务器的端口
new EchoClient(host, port).start();
}
}