1netty结构
419那个是以前网上看的,注解太少,不适合新手,后来又重新学习了下
论总结的重要性。。。
client发信息给Server,server再返回给client
2实现
Netty 服务器都需要下面这些:
一个服务器 handler:这个组件实现了服务器的业务逻辑,决定了连接创建后和接收到信息后该如何处理
上图中的ServerHandler,Echo Server 将会将接受到的数据的拷贝发送给客户端。
我们需要实现 ChannelInboundHandler接口,用来定义处理入站事件的方法。由于我们的应用很简单,只需要继承ChannelInboundHandlerAdapter 就行了。这个类 提供了默认 ChannelInboundHandler 的实现,所以只需要覆盖下面的方法:channelRead() - 每个信息入站都会调用
channelReadComplete() - 通知处理器最后的 channelread() 是当前批处理中的最后一条消息时调用
exceptionCaught()- 读操作时捕获到异常时调用
@Sharable
// 11. @Sharable 标识这类的实例之间可以在 channel 里面共享
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) {
ByteBuf in = (ByteBuf) msg;
System.out
.println("Server received: " + in.toString(CharsetUtil.UTF_8)); // 2.日志消息输出到控制台
ctx.write(in); // 3将所接收的消息返回给发送者。注意,这还没有冲刷数据
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)// 4.冲刷所有待审消息到远程节点。关闭通道后,操作完成
.addListener(ChannelFutureListener.CLOSE);
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace(); // 5打印异常堆栈跟踪
ctx.close(); // 6.关闭通道
}
}
是不是很详细,哈哈!!!
Bootstrapping: 这个是配置服务器的启动代码。最少需要设置服务器绑定的端口,用来监听连接请求
Echoserver.java就是了
public class EchoServer {
private final int port;//1端口号
public EchoServer(int port) {
this.port = port;
}
public static void main(String[] args) throws Exception {
new EchoServer(9090).start(); // 2呼叫服务器的 start()方法,就是你刚刚写的哪个类
}
public void start() throws Exception {
NioEventLoopGroup group = new NioEventLoopGroup(); // 3创建 EventLoopGroup
try {
ServerBootstrap b = new ServerBootstrap();
b.group(group) // 4创建 ServerBootstrap
.channel(NioServerSocketChannel.class) // 5指定使用 NIO 的传输 Channel
.localAddress(new InetSocketAddress(port)) // 6设置 socket 地址使用所选的端口
.childHandler(new ChannelInitializer<SocketChannel>() { // 7.添加 EchoServerHandler 到 Channel 的 ChannelPipeline
@Override
public void initChannel(SocketChannel ch)
throws Exception {
ch.pipeline().addLast(
new EchoServerHandler());
}
});
ChannelFuture f = b.bind().sync(); // 8绑定的服务器;sync 等待服务器关闭
System.out.println(EchoServer.class.getName()
+ " started and listen on " + f.channel().localAddress());
f.channel().closeFuture().sync(); // 9关闭 channel 和 块,直到它被关闭
} finally {
group.shutdownGracefully().sync(); // 10关机的 EventLoopGroup,释放所有资源
}
}
}
port是你自己写的端口号,一会和client写的对应就行了
服务器的主代码组件是
EchoServerHandler 实现了的业务逻辑在 main()方法,
引导了服务器
执行后者所需的步骤是:
创建 ServerBootstrap 实例来引导服务器并随后绑定
创建并分配一个 NioEventLoopGroup 实例来处理事件的处理,如接受新的连接和读/写数据。
指定本地 InetSocketAddress 给服务器绑定
通过 EchoServerHandler 实例给每一个新的 Channel 初始化
最后调用 ServerBootstrap.bind() 绑定服务器
好了,Server就写完了
写一个 echo 客户端客
户端要做的是:
连接服务器
发送信息
发送的每个信息,等待和接收从服务器返回的同样的信息
关闭连接
用 ChannelHandler 实现客户端逻辑跟写服务器一样,我们提供 ChannelInboundHandler 来处理数据。下面例子,我们用SimpleChannelInboundHandler 来处理所有的任务,需要覆盖三个方法:
channelActive() - 服务器的连接被建立后调用
channelRead0() - 数据后从服务器接收到调用
exceptionCaught() - 捕获一个异常时调用
@Sharable //1
public class EchoClientHandler extends
SimpleChannelInboundHandler<ByteBuf> {
@Override
public void channelActive(ChannelHandlerContext ctx) {
ctx.writeAndFlush(Unpooled.copiedBuffer("Netty rocks! hello Netty", //2
CharsetUtil.UTF_8));
}
@Override
public void channelRead0(ChannelHandlerContext ctx,
ByteBuf in) {
System.out.println("Client received: " + in.toString(CharsetUtil.UTF_8)); //3
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx,
Throwable cause) { //4
cause.printStackTrace();
ctx.close();
}
}
1. @Sharable 标记这个类的实例可以在 channel 里共享2.当被通知该 channel 是活动的时候就发送信息3.记录接收到的消息写一个 echo 客户端本文档使用 -4.记录日志错误并关闭 channel
引导客户端客户端引导需要 host 、port 两个参数连接服务器
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 {
Bootstrap b = new Bootstrap(); // 1
b.group(group) // 2
.channel(NioSocketChannel.class) // 3
.remoteAddress(new InetSocketAddress(host, port)) // 4
.handler(new ChannelInitializer<SocketChannel>() { // 5
@Override
public void initChannel(SocketChannel ch)
throws Exception {
ch.pipeline().addLast(
new EchoClientHandler());
}
});
ChannelFuture f = b.connect().sync(); // 6
f.channel().closeFuture().sync(); // 7
} finally {
group.shutdownGracefully().sync(); // 8
}
}
public static void main(String[] args) throws Exception {
new EchoClient("192.168.51.190", 9090).start();
}
}
1.创建 Bootstrap2.指定 EventLoopGroup 来处理客户端事件。由于我们使用 NIO 传输,所以用到了NioEventLoopGroup 的实现3.使用的 channel 类型是一个用于 NIO 传输4.设置服务器的 InetSocketAddress5.当建立一个连接和一个新的通道时,创建添加到 EchoClientHandler 实例 到 channel pipeline6.连接到远程;等待连接完成7.阻塞直到 Channel 关闭8.调用 shutdownGracefully() 来关闭线程池和释放所有资源
一个 Bootstrap 被创建来初始化客户端一个 NioEventLoopGroup 实例被分配给处理该事件的处理,这包括创建新的连接和处理入站和出站写一个 echo 客户端本文档使用 -数据一个 InetSocketAddress 为连接到服务器而创建一个 EchoClientHandler 将被安装在 pipeline 当连接完成时之后 Bootstrap.connect()被调用连接到远程的 - 本例就是 echo(回声)服务器
运行两个mian函数,就能看到结果了
看不懂?没事,还有netty
netty学习四,对上面用到的组件进行了讲解