Use Netty to simply achieve a chat room function.

  • Project Required Dependencies
<dependency>
            <groupId>io.netty</groupId>
            <artifactId>netty-all</artifactId>
            <version>4.1. 50.Final</version>
</dependency>
Copy the code

The client

   public class server {
   public static void main(String[] args) {
       EventLoopGroup boss = new NioEventLoopGroup(1);
       EventLoopGroup work = new NioEventLoopGroup();
       try {
           ServerBootstrap bootstrap = new ServerBootstrap();
           bootstrap.group(boss,work)
                   .channel(NioServerSocketChannel.class)
                   .option(ChannelOption.SO_BACKLOG,1024)
                   .childHandler(new ChannelInitializer<SocketChannel>() {
                       @Override
                       protected void initChannel(SocketChannel socketChannel) throws Exception {
                           ChannelPipeline pipeline = socketChannel.pipeline();
                           pipeline.addLast("decoder".new StringDecoder());/ / decoder
                           pipeline.addLast("encoder".new StringEncoder());/ / encoder
                           pipeline.addLast(newNettyServerHandler()); }}); ChannelFuture sync = bootstrap.bind(8888).sync();// Netty is a non-blocking asynchrony. In this case, it is best to make sure that the execution is done first before using the server to do business.
           System.out.println("Chat room launched successfully");
           sync.channel().closeFuture().sync();
       } catch (Exception e) {
           e.printStackTrace();
       } finally{ boss.shutdownGracefully(); work.shutdownGracefully(); }}}Copy the code

The client handler

public class NettyServerHandler extends SimpleChannelInboundHandler<String> {
// channelGroup stores all channels connected to the server
// You can call channelGroup's size method to see how many connecters are currently connected
    private static ChannelGroup channelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);
    SimpleDateFormat simpleDateFormat = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    This method is triggered when a message is read
    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String s) throws Exception {
        Channel channel = ctx.channel();
        channelGroup.forEach(ch->{
        // Distinguish the current user from other users
            if(ch! =channel){ ch.writeAndFlush("Client:"+channel.remoteAddress()+"Message sent"+s+"\n");
            }else {
                ch.writeAndFlush("Myself:"+channel.remoteAddress()+"Message sent"+s+"\n"); }}); }// Netty automatically calls this interface when a new link is created
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        Channel channel=ctx.channel();
        channelGroup.writeAndFlush("Client:"+channel.remoteAddress()+"Online"+""+simpleDateFormat.format(new Date()));
        channelGroup.add(channel);
        System.out.println(channel.remoteAddress()+"Online");
    }
    // This is automatically called when there is a broken link
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        Channel channel = ctx.channel();
        channelGroup.writeAndFlush("Client:"+channel.remoteAddress()+"Offline");
        System.out.println(channel.remoteAddress()+"Offline"); }}Copy the code

The service side

/ * * *@Author Weng
 * @Description
 * @Date2021/1/18 young * /

public class client {
    public static void main(String[] args) {
        EventLoopGroup boss = new NioEventLoopGroup();
        try {
            Bootstrap bootstrap = new Bootstrap();
            bootstrap.group(boss)
                    .channel(NioSocketChannel.class)
                    .handler(new ChannelInitializer<SocketChannel>() {
                        @Override
                        protected void initChannel(SocketChannel socketChannel) throws Exception {
                            ChannelPipeline pipeline = socketChannel.pipeline();
                            pipeline.addLast("decoder".new StringDecoder());
                            pipeline.addLast("encoder".new StringEncoder());
                            pipeline.addLast(newNettyClientHandler()); }});// Connect to the corresponding server open port
            ChannelFuture sync = bootstrap.connect("127.0.0.1".8888).sync();
            Channel channel = sync.channel();
            Scanner scanner = new Scanner(System.in);
            while(scanner.hasNextLine()){ String s = scanner.nextLine(); channel.writeAndFlush(s); }}catch (Exception e) {
            e.printStackTrace();
        } finally{ boss.shutdownGracefully(); }}}Copy the code

The client handler

public class NettyClientHandler extends SimpleChannelInboundHandler<String> {

    @Override
    protected void channelRead0(ChannelHandlerContext channelHandlerContext, String s) throws Exception {
    // The client directly prints the received server messageSystem.out.println(s); }}Copy the code
  • According to Netty’s core threading model, user connections are handled by a NioEventLoopGroup (BOOS) that can generate multiple threads through constructors (A thread corresponds to a NioEventLoopGroup) to process user connection requests. Boos registers the channel generated after the connection to a selector in the work, responds to the user’s message processing in the work, and dumps all events to Popeline for execution. Popeline has our custom handler (which is also the business logic code we mainly write), encoders and decoders are registered in Popeline.
    • EventLoopGroup boss = new NioEventLoopGroup(1);
    • EventLoopGroup work = new NioEventLoopGroup();