Netty(二)Discard Server 与 ChannelInitializer

Server端代码:

public class DiscardServer {private static final int PORT_NUM = Integer.parseInt(System.getProperty("port", "6767"));public void run() throws CertificateException, SSLException {EventLoopGroup bossGroup = new NioEventLoopGroup(); // 用于accept incomming连接请求EventLoopGroup workerGroup = new NioEventLoopGroup(); // 程序将accepted连接请求注册到workerGroup中,并由里面的线程跟踪处理相关“traffic”try {ServerBootstrap sb = new ServerBootstrap(); // “helper class” 2 set up a serversb.group(bossGroup, workerGroup).channel(NioServerSocketChannel.class) // 利用 NioServerSocketChannel class 的初始化Server端的Channel实例来accept连接请求.handler(new LoggingHandler(LogLevel.INFO)) // 设置handler,.childHandler(new DiscardServerInitializer()); // 设置另外一个handler,childHanlder与handler的不同会在后续博文中描述,Handler在Netty是一个很重要的地位,相当于Servlet中的filter一样,这里用一个ChannelInitializer来统一管理所有handler// bind and start to accept incoming connectionsChannelFuture cf = sb.bind(PORT_NUM).sync(); // 绑定端口,并利用sync()方法开始监听端口(等待客户端连接请求),若成功,返回ChannelFuture,ChannelFuture也会在后续详细说明// Wait until the server socket is closed// 本例中,下面一行代码永远不会发生,但可以用于正常关闭server// 监听服务关闭监听cf.channel().closeFuture().sync();} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();} finally {bossGroup.shutdownGracefully(); // 相当于是关闭线程池workerGroup.shutdownGracefully();}}public static void main(String[] args) throws CertificateException, SSLException {DiscardServer server = new DiscardServer();server.run();}}

Client端代码:

public class DiscardClient {private static final String REMOET_HOST = System.getProperty("host", "127.0.0.1");private static final int REMOTE_PORT = Integer.parseInt(System.getProperty("port", "6767"));public static final int BUFFER_SIZE = Integer.parseInt(System.getProperty("size", "8192"));public void run() throws SSLException, CertificateException, InterruptedException {EventLoopGroup group = new NioEventLoopGroup();try {Bootstrap bs = new Bootstrap();bs.group(group).channel(NioSocketChannel.class).handler(new DiscardClientInitializer());// make the connection attemptChannelFuture f = bs.connect(REMOET_HOST, REMOTE_PORT).sync();// Wait until the connection is closedf.channel().closeFuture().sync();} finally {group.shutdownGracefully();}}}

Initializer(Server与Client的几乎是通用的):

public class DiscardServerInitializer extends ChannelInitializer<SocketChannel> {private static final boolean SSL = System.getProperty("ssl") != null;private final SslContext sslCtx;public DiscardServerInitializer() throws SSLException, CertificateException {if (SSL) {// 如果是需要使用SSL加密传输,则初始化并获取一个self-signed certificate 4 testingSelfSignedCertificate ssc = new SelfSignedCertificate();// 返回一个openJDK默认的X509临时证书生成文件和密钥文件sslCtx = SslContext.newServerContext(ssc.certificate(), ssc.privateKey());} else {sslCtx = null;}}@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// 从SocketChannel中获得管道ChannelPipeline pipeline = ch.pipeline();<pre name="code" class="java">// 都属于ChannelOutboundHandler,按逆序执行if (sslCtx != null) {// 安全通信通道pipeline.addLast(sslCtx.newHandler(ch.alloc())); // 字符串}pipeline.addLast("encoder", new StringEncoder());// 都属于ChannelInboundHandler,顺序执行pipeline.addLast("frame", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));pipeline.addLast("decoder", new StringDecoder()); // 字符串解码// 自定义handlerpipeline.addLast("handler", new DiscardServerHandler());}}

ChannelInitializer的主要目的是为SocketChannel注册Handler,也就是当一个SocketChannel被Server accept 进来以后,,进来的数据要分别按注册先后顺序执行哪些handler,出去的数据要分别按逆序的顺序执行哪些handler!这里的注册handler的先后顺序十分重要,ChannelInboundHandler都是按顺序执行的,ChanneloutboundHandler都是按逆序的顺序执行的如下图所示:

同时需要说明一点的是:(下面##之间的说法有误,修正在下面)

###########################################################################################################################

client端和server端的Inbound和Outbound顺序应该刚好相反如下所示:

Server:

@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// 从SocketChannel中获得管道ChannelPipeline pipeline = ch.pipeline();// 都属于ChannelInboundHandler,顺序执行pipeline.addLast("frame", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));pipeline.addLast("decoder", new StringDecoder()); // 字符串解码// 自定义handlerpipeline.addLast("handler", new DiscardServerHandler());// 都属于ChannelOutboundHandler,按逆序执行if (sslCtx != null) {// 安全通信通道pipeline.addLast(sslCtx.newHandler(ch.alloc())); // 字符串}pipeline.addLast("encoder", new StringEncoder());}Client:@Overrideprotected void initChannel(SocketChannel ch) throws Exception {// 这里要和服务器对应起来// 否则无法正常解码和编码ChannelPipeline pipeline = ch.pipeline();// 都属于ChannelOutboundHandler,按逆序执行if (sslCtx != null) {// 安全通信通道pipeline.addLast(sslCtx.newHandler(ch.alloc())); // 字符串}pipeline.addLast("encoder", new StringEncoder());// 从SocketChannel中获得管道pipeline.addLast("frame", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));// 字符串解码、编码pipeline.addLast("decoder", new StringDecoder());// 自定义handlerpipeline.addLast("handler", new DiscardClientHandler());}

最美不过偷瞄你是你忽然转头,看见你的微笑

Netty(二)Discard Server 与 ChannelInitializer

相关文章:

你感兴趣的文章:

标签云: