Netty学习摘记 —— Netty客户端 / 服务端概览

本文参考

本篇文章是对《Netty In Action》一书第二章"你的第一款 Netty 应用程序"的学习摘记,主要内容编写 Echo 服务器和客户端

第一款应用程序的功能

Echo 客户端和服务器之间的交互十分简单:在客户端建立一个连接之后,它会向服务器发送一个或多个消息,反过来,服务器又会将每个消息回送给客户端。虽然我们的主要关注点可能是编写基于 Web 的用于被浏览器访问的应用程序,但它也充分地体现了客户端/服务器系统中典型的请求-响应交互模式。

编写Echo服务器

ChannelHandler是一个接口族的父接口,它的许多实现可以负责接收并响应事件通知。 在 Netty 应用程序中,所有的数据处理逻辑都包含在这些核心抽象的实现中

因为我们的Echo 服务器会响应传入的消息,所以它需要实现ChannelInboundHandler接口,用来定义响应入站事件的方法。这个简单的应用程序只需要用到少量的这些方法,所以继承 ChannelInboundHandlerAdapter类也就足够了,它提供了ChannelInboundHandler的默认实现

在这里我们用到了

channelRead() — Invoked when the current Channel has read a message from the peer

channelReadComplete() —— Invoked when the last message read by the current read operation has been consumed by channelRead(ChannelHandlerContext, Object).

exceptionCaught() —— Gets called if a Throwable class was thrown.

//标示一个ChannelHandler可以被多个 Channel 安全地共享
@Sharable
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));
//
将接收到的消息写给发送者,而不冲刷出站消息
ctx.write(in);
}

@Override
public void channelReadComplete(ChannelHandlerContext ctx)
throws Exception {
//
未冲刷的消息冲刷到远程节点,并且关闭该 Channel
ctx.writeAndFlush(Unpooled.EMPTY_BUFFER)
.addListener(ChannelFutureListener.CLOSE);
}

@Override
public void exceptionCaught(ChannelHandlerContext ctx,
Throwable cause) {
//
打印异常栈跟踪
cause.printStackTrace();
//
关闭该Channel
ctx.close();
}
}

异常捕获机制:

每个 Channel 都拥有一个与之相关联的 ChannelPipeline,其持有一个 ChannelHandler 的 实例链。在默认的情况下,ChannelHandler 会把对它的方法的调用转发给链中的下一个 ChannelHandler。因此,如果exceptionCaught()方法没有被该链中的某处实现,那么所接收的异常将会被传递到 ChannelPipeline 的尾端并被记录。为此,应用程序应该提供至少有一个实现了 exceptionCaught()方法的ChannelHandler

@Sharable注解也有涉及ChannelPipeline的概念,当前的ChannelHandler被注解为Sharable时,可以在不存在竞争的情况下添加到多个ChannelPipeline中,否则因成员变量无法共享,需要每次都新建一个ChannelHandler实例添加到ChannelPipeline

Indicates that the same instance of the annotated ChannelHandler can be added to one or more ChannelPipeline multiple times without a race condition.

If this annotation is not specified, you have to create a new handler instance every time you add it to a pipeline because it has unshared state such as member variables.

 

 

 

 

 

 

猜你喜欢

转载自www.cnblogs.com/kuluo/p/12611561.html