Introduction and introduction to 03RPC - netty

Keywords: Netty network Java socket

Netty is a network application framework based on Java NIO.

Netty is a NIO client-server (client server) framework, using Netty can quickly develop network applications, such as server and client protocols. Netty provides a new way to develop network applications, which makes it easy to use and extensible. Netty's internal implementation is complex, but Netty provides an easy-to-use api to decouple business logic from network processing code. Netty is implemented entirely on NIO, so the whole Netty is asynchronous. Network applications usually need to be highly scalable, whether Netty or other Java NIO-based frameworks, will provide scalable solutions.

A key component of Netty is its asynchronous nature

Let's look at an introductory case:

1. Download the netty package

Download netty package, download address http://netty.io/

2. Server Startup Class

/**
 * • Configure server functions, such as threads, ports, and implementations of server handlers, which contain business logic to determine what to do when a request connects or receives data
 * 
 *
 */
public class EchoServer {

	private final int port;

	public EchoServer(int port) {
		this.port = port;
	}

	public void start() throws Exception {
		EventLoopGroup eventLoopGroup = null;
		try {
			//Create a ServerBootstrap instance to boot the binding and start the server
			ServerBootstrap serverBootstrap = new ServerBootstrap();
			
			//Create NioEventLoopGroup objects to handle events, such as accepting new connections, receiving data, writing data, and so on.
			eventLoopGroup = new NioEventLoopGroup();
			
			//Specify the channel type as NioServerSocket Channel, and set InetSocket Address to let the server listen for a port that has been waiting for the client to connect.
			serverBootstrap.group(eventLoopGroup).channel(NioServerSocketChannel.class).localAddress("localhost",port).childHandler(new ChannelInitializer<Channel>() {
				//Set up child handler to execute all connection requests
				@Override
				protected void initChannel(Channel ch) throws Exception {
					ch.pipeline().addLast(new EchoServerHandler());
				}
					});
			
			// Finally, the binding server waits until the binding is complete, calling the sync() method blocks until the server completes the binding, and then the server waits for the channel to close, because using sync(), the closing operation will also be blocked.
			ChannelFuture channelFuture = serverBootstrap.bind().sync();
			System.out.println("Start listening, port is:" + channelFuture.channel().localAddress());
			channelFuture.channel().closeFuture().sync();
		} finally {
			eventLoopGroup.shutdownGracefully().sync();
		}
	}

	public static void main(String[] args) throws Exception {
		new EchoServer(20000).start();
	}
}

3. Service-side callback method

public class EchoServerHandler extends ChannelInboundHandlerAdapter {

	@Override
	public void channelRead(ChannelHandlerContext ctx, Object msg)
			throws Exception {
		System.out.println("server Read data...");
		
		//Read data
        ByteBuf buf = (ByteBuf) msg;
        byte[] req = new byte[buf.readableBytes()];
        buf.readBytes(req);
        String body = new String(req, "UTF-8");
        System.out.println("Receiving client data:" + body);
        
        //Write data to client
        System.out.println("server towards client send data");
        String currentTime = new Date(System.currentTimeMillis()).toString();
        ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());
        ctx.write(resp);
	}

	@Override
	public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
		System.out.println("server Read the data...");
        ctx.flush();//Data is sent to Socket Channel only after refresh
	}

	@Override
	public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
			throws Exception {
		cause.printStackTrace();
		ctx.close();
	}

4. Client Startup Class

/**
 * • Connect the server, write data to the server, wait for the receiving server to return the same data, close the connection
 * 
 *
 */
public class EchoClient {

	private final String host;
	private final int port;

	public EchoClient(String host, int port) {
		this.host = host;
		this.port = port;
	}

	public void start() throws Exception {
		EventLoopGroup nioEventLoopGroup = null;
		try {
			//Create a Bootstrap object to boot the client
			Bootstrap bootstrap = new Bootstrap();
			
			//Create EventLoopGroup objects and set them in Bootstrap. EventLoopGroup can be understood as a thread pool that handles connections, receives data, and sends data.
			nioEventLoopGroup = new NioEventLoopGroup();
			
			//Create InetSocket Address and set it to Bootstrap, where InetSocket Address is the server address for the specified connection
			bootstrap.group(nioEventLoopGroup).channel(NioSocketChannel.class).remoteAddress(new InetSocketAddress(host, port))
					.handler(new ChannelInitializer<SocketChannel>() {
						//Add a ChannelHandler and the client will be executed after successfully connecting to the server.
						@Override
						protected void initChannel(SocketChannel ch)
								throws Exception {
							ch.pipeline().addLast(new EchoClientHandler());
						}
					});
			
			// Call Bootstrap.connect() to connect to the server
			ChannelFuture f = bootstrap.connect().sync();
			
			// Close EventLoopGroup to release resources
			f.channel().closeFuture().sync();
		} finally {
			nioEventLoopGroup.shutdownGracefully().sync();
		}
	}

	public static void main(String[] args) throws Exception {
		new EchoClient("localhost", 20000).start();
	}
}

5. Client Callback Method

	  
	public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {  
	      //The client is called after connecting to the server
	    @Override  
	    public void channelActive(ChannelHandlerContext ctx) throws Exception {  
	    	System.out.println("The client connects to the server and starts sending data...");
	    	byte[] req = "QUERY TIME ORDER".getBytes();
	    	ByteBuf  firstMessage = Unpooled.buffer(req.length);
	        firstMessage.writeBytes(req);
	        ctx.writeAndFlush(firstMessage);  
	    }  
	  
	  //Call after data is received from the server
	    @Override  
	    protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg) throws Exception {  
	    	 System.out.println("client read server data..");
	         //After the server returns the message
	         ByteBuf buf = (ByteBuf) msg;
	         byte[] req = new byte[buf.readableBytes()];
	         buf.readBytes(req);
	         String body = new String(req, "UTF-8");
	         System.out.println("Server-side data is :" + body);
}  
	  
	  //When an exception occurs, it is called
	    @Override  
	    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {  
	    	 System.out.println("client exceptionCaught..");
	         // Releasing resources
	         ctx.close(); 
	    }  
	}  

Posted by lnenad on Wed, 09 Oct 2019 22:42:45 -0700