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(); } }