Netty 4.x Chinese tutorial series Hello World

Posted by erikwebb on Sun, 08 Sep 2019 16:57:55 +0200

Links to the original text: https://my.oschina.net/u/1781072/blog/542608

1. Download and add Netty framework to the project
1.Netty's packages can be accessed from Netty's official website: http://netty.io/downloads.html download

Netty provides four major versions of the framework package for download.
Version 3.9 final indicates that this version is the latest version in version 3.x. final means that the function no longer continues to add updates. Continuous updates are provided only for bug modifications, etc.
Version 5.x is the beginning. It is impossible to exclude the problems of stable operation. Plus 5.x with minor modifications to the 4.x version. Before 5.x stabilizes. It is not recommended that you learn to use it.
This tutorial is based on Netty 4.x.
I deployed it through maven. The configuration is as follows:

    <dependency>
           <groupId>io.netty</groupId>
           <artifactId>netty-all</artifactId>
           <version>4.0.0.Final</version>
    </dependency>

2. Create Server Server
Netty creation is all implemented from AbstractBootstrap. The client side is Bootstrap and the server side is Server Bootstrap.

package mjorcen.netty.test1;

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioServerSocketChannel;

public class HelloServer {

    /** * Port Address for Server Listening */
    private static final int portNumber = 7878;

    public static void main(String[] args) throws InterruptedException {
        EventLoopGroup bossGroup = new NioEventLoopGroup();
        EventLoopGroup workerGroup = new NioEventLoopGroup();
        try {
            ServerBootstrap b = new ServerBootstrap();
            b.group(bossGroup, workerGroup);
            b.channel(NioServerSocketChannel.class);
            b.childHandler(new HelloServerInitializer());

            // Server Binding Port Listening
            ChannelFuture f = b.bind(portNumber).sync();
            // Sniffer Server Closes Sniffer
            f.channel().closeFuture().sync();

            // It can be abbreviated as
            /* b.bind(portNumber).sync().channel().closeFuture().sync(); */
        } finally {
            bossGroup.shutdownGracefully();
            workerGroup.shutdownGracefully();
        }
    }
}

EventLoopGroup is a new concept proposed in version 4.x. Used for channel management. The server needs two. Like version 3.x, one is the boss thread and the other is the worker thread.
B. child Handler (new Hello Server Initializer (); // Used to add relevant Handler
Simple code on the server side, there is really no way to streamline the feeling. It's a binding port operation.

2.2 Create and implement HelloServer Initializer
Hello Server Initializer in Hello Server is implemented here.
  

package mjorcen.netty.test1;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class HelloServerInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();

        // With ("\n")Decoder for End Segmentation
        pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192,
                Delimiters.lineDelimiter()));

        // String decoding and encoding
        pipeline.addLast("decoder", new StringDecoder());
        pipeline.addLast("encoder", new StringEncoder());

        // My own logical Handler
        pipeline.addLast("handler", new HelloServerHandler());
    }
}

First, we need to be clear about what we are going to do. It's simple. Hello World!. We want to achieve a function that can send text like a server. If the server can best return the point message to the client, then the client will display it.
The demand is simple. So we're going to start doing that next.
The example provided by Delimiter BasedFrameDecoder Netty on the official website shows that such a decoder can be used for simple message segmentation.
Secondly, we found String decoder in decoder. All of them are provided to us by the official website.

The above three decoding and coding are all systems.
What about our own Andler? Finally, we add our own Handler to write our own processing logic.
2.3 Add your own logic Hello Server Handler
We will inherit the Simple Channel Inbound Handler recommended by extends. Here in C, because what we need to send is a string. C here is rewritten to String.
  

package mjorcen.netty.test1;

import java.net.InetAddress;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

public class HelloServerHandler extends SimpleChannelInboundHandler<String> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg)
            throws Exception {
        // Receive the message and print it out directly
        System.out.println(ctx.channel().remoteAddress() + " Say : " + msg);

        // Return Client Message - I've received your message
        ctx.writeAndFlush("Received your message !\n");
    }

    /* * * The override channelActive method triggers when the channel is enabled (when the connection is established)** channelActive and channelInActive are described later, but not in detail here. */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {

        System.out.println("RamoteAddress : " + ctx.channel().remoteAddress()
                + " active !");

        ctx.writeAndFlush("Welcome to "
                + InetAddress.getLocalHost().getHostName() + " service!\n");

        super.channelActive(ctx);
    }
}

A writeAndFlush method comes with channelHandlerContent. The function of the method is to write to the Buffer and brush in.
Note: There is a big difference in version 3.x. In version 3.x, the write() method is automatic flush. The same is true for the previous versions of version 4.x. But it was changed to WriteAndFlush after 4.0.9. Normal write methods will not send messages. You need to flush() once after write manually
channeActive here means to trigger the remote address of the output message source when the connection is active. And return the welcome message.
channelRead0 here acts like messageReceived() in version 3.x. You can think of it as triggering every time you receive a message.
Our code here is to return a string of "Received your message!" from the client.
Note: The " n" at the end of the string is required. Because our previous decoder, DelimiterBasedFrameDecoder, ends with " n" at the end of the string. If there is no such character. Decoding can be problematic.

2.Client client
Similar to server-side code. We don't give a very detailed explanation.
Direct to the sample code:
  

package mjorcen.netty.test1;

import io.netty.bootstrap.Bootstrap;
import io.netty.channel.Channel;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;

public class HelloClient {

    public static String host = "127.0.0.1";
    public static int port = 7878;

    /** * @param args * @throws InterruptedException * @throws IOException */
    public static void main(String[] args) throws InterruptedException,
            IOException {
        EventLoopGroup group = new NioEventLoopGroup();
        try {
            Bootstrap b = new Bootstrap();
            b.group(group).channel(NioSocketChannel.class)
                    .handler(new HelloClientInitializer());

            // Connect the server
            Channel ch = b.connect(host, port).sync().channel();

            // Console input
            BufferedReader in = new BufferedReader(new InputStreamReader(
                    System.in));
            for (;;) {
                String line = in.readLine();
                if (line == null) {
                    continue;
                }
                /* * Send the text entered in the console to the server and end with "r\n" because we added * DelimiterBasedFrameDecoder frame decoding in handler. * This decoder is a decoder based on the n symbol bit separator. So every message must end with n, otherwise it cannot be recognized and decoded. */
                ch.writeAndFlush(line + "\r\n");
            }
        } finally {
            // The connection is closed automatically on shutdown.
            group.shutdownGracefully();
        }
    }
}

Below is the HelloClient Initializer code that looks exactly the same as the server. I didn't pay attention to it. In fact, encoding and decoding are relative. Most of the servers and clients are decoded and coded. Only then can we communicate.

package mjorcen.netty.test1;

import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;
import io.netty.handler.codec.DelimiterBasedFrameDecoder;
import io.netty.handler.codec.Delimiters;
import io.netty.handler.codec.string.StringDecoder;
import io.netty.handler.codec.string.StringEncoder;

public class HelloClientInitializer extends ChannelInitializer<SocketChannel> {

    @Override
    protected void initChannel(SocketChannel ch) throws Exception {
        ChannelPipeline pipeline = ch.pipeline();

        /* * This place must correspond to the server. Otherwise, the normal decoding and encoding ** decoding and encoding will be explained in detail in the next one. Again, no detailed description will be given for the time being. */
        pipeline.addLast("framer", new DelimiterBasedFrameDecoder(8192,
                Delimiters.lineDelimiter()));
        pipeline.addLast("decoder", new StringDecoder());
        pipeline.addLast("encoder", new StringEncoder());

        // Client Logic
        pipeline.addLast("handler", new HelloClientHandler());
    }
}

HellClientHandler:

package org.example.hello;

import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.SimpleChannelInboundHandler;

public class HelloClientHandler extends SimpleChannelInboundHandler<String> {

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, String msg) throws Exception {

        System.out.println("Server say : " + msg);
    }

    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("Client active ");
        super.channelActive(ctx);
    }

    @Override
    public void channelInactive(ChannelHandlerContext ctx) throws Exception {
        System.out.println("Client close ");
        super.channelInactive(ctx);
    }
}

Sample source code for this tutorial: http://pan.baidu.com/s/1hABzK#dir
You can find it in my Baidu Yunpan.
Achievements:
The client outputs Client activity information in connection establishment and receives Welcome message returned by the server.
Enter Hello World! Enter and send a message. The server responded that the return message was accepted.
server side:
RamoteAddress : /127.0.0.1:34202 active !
/127.0.0.1:34202 Say : hello server
client side
Client active
Server say : Welcome to Q12MB1DR67JGLJT service!
hello server
Server say : Received your message !

Reproduced in: https://my.oschina.net/u/1781072/blog/542608

Topics: Netty codec socket encoding