莫大人

netty学习

1、参考地址

https://waylau.gitbooks.io/netty-4-user-guide/content/Architectural-Overview/Universal-Asynchronous-IO-API.html

https://github.com/waylau/netty-4-user-guide-demos

2、服务端

以上为关键步骤,服务端处理器,渠道设置,通道设置,也就是第4步。

以下为建一个服务端为例

2.1、初始化ServerBootstrap实例,此实例是netty应用开发的入口

2.2、创建Reactor主线程池,用于接收客户端请求的线程池职责

2.2.1、接收客户端TCP连接,初始化 Channel参数

2.2.2、将链路状态变更事件通知给 Channelpipeline

2.3、创建Reactor从线程池

2.3.1、异步读取通信对端的数据报,发送读事件到 Channelpipeline;

2.3.2、异步发送消息到通信对端,调用 Channelpipeline的消息发送接口;

2.3.3、执行系统调用Task;

2.3.4、执行定时任务Task,例如链路空闲状态监测定时任务.

2.4、设置netty主从线程池

2.5、设置Channel

2.6、childGroup的处理器,用来管理通道

2.7、设置选项 SO_BACKLOG 设置线程队列的链接个数

2.8、SO_KEEPALIVE 设置保持链接活动连接状态

2.9、绑定端口

2.10、关闭线程池

 

3、客户端

 

 

 

对于服务端核心在于设置childHandler,对于客户端核心在于设置handler。

服务端示例

public class SimpleChatServer{

	public static void main(String[] args) {
		ServerBootstrap boot = new ServerBootstrap();
		EventLoopGroup parentGroup = new NioEventLoopGroup();
		EventLoopGroup childGroup = new NioEventLoopGroup();
		
		try {
			boot.group(parentGroup, childGroup);
			boot.channel(NioServerSocketChannel.class);
			boot.childHandler(new SimpleChatServerInitializer());
			boot.option(ChannelOption.SO_BACKLOG, 128);
			boot.childOption(ChannelOption.SO_KEEPALIVE, true);
			boot.bind(NettyConstant.PORT).sync().channel().closeFuture().sync();
		} catch (InterruptedException e) {
			e.printStackTrace();
		} finally {
			parentGroup.shutdownGracefully();
			childGroup.shutdownGracefully();
		}
		
		
	}
	
}

  

public class SimpleChatServerInitializer extends ChannelInitializer<SocketChannel> {

	@Override
	protected void initChannel(SocketChannel ch) throws Exception {
		ChannelPipeline pipeline = ch.pipeline();
		pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
        pipeline.addLast("decoder", new StringDecoder());
        pipeline.addLast("encoder", new StringEncoder());
        pipeline.addLast("handler", new SimpleChatServerHandler());
	}

}

  

public class SimpleChatServerHandler extends SimpleChannelInboundHandler<String> { // (1)
	
	/**
	 * A thread-safe Set  Using ChannelGroup, you can categorize Channels into a meaningful group.
	 * A closed Channel is automatically removed from the collection,
	 */
	public static ChannelGroup channels = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    @Override
    public void handlerAdded(ChannelHandlerContext ctx) throws Exception {  // (2)
        Channel incoming = ctx.channel();
        
        // Broadcast a message to multiple Channels
        channels.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 加入\n");
        
        channels.add(ctx.channel());
    }

    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) throws Exception {  // (3)
        Channel incoming = ctx.channel();
        
        // Broadcast a message to multiple Channels
        channels.writeAndFlush("[SERVER] - " + incoming.remoteAddress() + " 离开\n");
        
        // A closed Channel is automatically removed from ChannelGroup,
        // so there is no need to do "channels.remove(ctx.channel());"
    }
    @Override
	protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception { // (4)
		Channel incoming = ctx.channel();
		for (Channel channel : channels) {
            if (channel != incoming){
                channel.writeAndFlush("[" + incoming.remoteAddress() + "]" + s + "\n");
            } else {
            	channel.writeAndFlush("[you]" + s + "\n");
            }
        }
	}
  
	@Override
	public void channelActive(ChannelHandlerContext ctx) throws Exception { // (5)
        Channel incoming = ctx.channel();
		System.out.println("SimpleChatClient:"+incoming.remoteAddress()+"在线");
	}
	
	@Override
	public void channelInactive(ChannelHandlerContext ctx) throws Exception { // (6)
        Channel incoming = ctx.channel();
		System.out.println("SimpleChatClient:"+incoming.remoteAddress()+"掉线");
	}
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) { 
    	Channel incoming = ctx.channel();
		System.out.println("SimpleChatClient:"+incoming.remoteAddress()+"异常");
        // 当出现异常就关闭连接
        cause.printStackTrace();
        ctx.close();
    }
}

  客户端示例

public class SimpleChatClient {

	public static void main(String[] args) {
		Bootstrap boot = new Bootstrap();
		EventLoopGroup parentGroup = new NioEventLoopGroup();
		
		try {
			boot.group(parentGroup);
			boot.channel(NioSocketChannel.class);
			boot.handler(new SimpleChatClientInitializer());
			boot.option(ChannelOption.SO_BACKLOG, 128);
			
			Channel channel = boot.connect(NettyConstant.HOST, NettyConstant.PORT).sync().channel();
			
			BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
            while(true){
                channel.writeAndFlush(in.readLine() + "\r\n");
            }
            
		} catch (InterruptedException e) {
			e.printStackTrace();
		} catch (IOException e) {
			e.printStackTrace();
		} finally {
			parentGroup.shutdownGracefully();
		}
		
		
	}
	
}

  

public class SimpleChatClientInitializer extends ChannelInitializer<SocketChannel> {

	@Override
    public void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();
        
        pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
        pipeline.addLast("decoder", new StringDecoder());
        pipeline.addLast("encoder", new StringEncoder());
        pipeline.addLast("handler", new SimpleChatClientHandler());
    }
	
}

  

public class SimpleChatClientHandler extends  SimpleChannelInboundHandler<String> {

	@Override
	protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception {
		System.out.println(s);
	}
	
}

  

 

posted on 2020-12-24 17:16  莫大人  阅读(82)  评论(0编辑  收藏  举报

导航