This example first introduces the Java native API to achieve BIO communication, then advanced to achieve NIO communication, finally using Netty to achieve NIO communication and the main module components of Netty.

Netty is an asynchronous event-driven network application framework for rapid development of maintainable high-performance protocol servers and clients.

BIO (Blocking I/O) solution

The BIO communication (one request, one reply) model is shown below

For a server that uses the BIO communication model, a separate Acceptor thread is usually responsible for listening for client connections. We generally listen for requests by calling the accept() method in the while(true) loop. Once we receive a connection request, we can read and write on this communication socket. At this time, we cannot receive other client connection requests. If the BIO communication model is to be able to handle multiple client requests at the same time, You must use multithreading (mainly because the three main functions involved in socket.accept(), socket.read(), and socket.write() all block synchronously)

Code implementation

BIO server

BIOServer.java

package com.easy.javaBio; import lombok.SneakyThrows; import lombok.extern.slf4j.Slf4j; import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.net.ServerSocket; import java.net.Socket; @Slf4j public class BIOServer { public static void main(String[] args) throws IOException { ServerSocket server = new ServerSocket(10002); while (true) { Socket client = server.accept(); If no connection is obtained, wait for new Thread(new ServerThread(client)).start(); // start a thread for each client connection} //server.close(); } } @Slf4j class ServerThread extends Thread { private Socket client; public ServerThread(Socket client) { this.client = client; } @sneakythrows @override public void run() {log.info(" client :" + client.getinetAddress ().getLocalhost () + "Connected to the server "); BufferedReader br = new BufferedReader(new InputStreamReader(client.getInputStream())); String Mess = br.readline (); Log.info (" client: "+ mess); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(client.getOutputStream())); bw.write(mess + "\n"); bw.flush(); }}Copy the code

BIO client

BIOClient.java

package com.easy.javaBio; import lombok.extern.slf4j.Slf4j; import java.io.*; import java.net.Socket; @Slf4j public class BIOClient { public static void main(String[] args) throws IOException { Socket s = new The Socket (" 0.0.0.0 ", 10002); InputStream input = s.getInputStream(); OutputStream output = s.getOutputStream(); BufferedWriter bw = new BufferedWriter(new OutputStreamWriter(output)); Bw. Write (" client sends message to server test \n"); // Send a message to the server bw.flush(); BufferedReader br = new BufferedReader(new InputStreamReader(input)); String Mess = br.readline (); Log.info (" server: "+ mess); }}Copy the code

Run the example

Run the BIO server, then run the BIO client, and watch the console

BIOServer console output:

Connected to the target VM, address: '127.0.0.1:64346', transport: 'socket 17:29:52. 519 INFO com [Thread - 1]. Easy. JavaBio. ServerThread - client: YHE6OR5UXQJ6D35/192.168.9.110 is connected to the server 17:29:52. [523] Thread - 1 the INFO com. Easy. JavaBio. ServerThread - client: the client to the server message testCopy the code

BIOClient console output:

Connected to the target VM, address: '127.0.0.1:64355', transport: 'socket 17:29:52. 527. [the main] INFO com. Easy. JavaBio. BIOClient - server: Disconnected from the target VM, address: '127.0.0.1:64355', transport: 'socket'Copy the code

This means that we have implemented a simple BIO communication

This mode enables one thread for each client. In high concurrency, resources are consumed, wasted, and even the server crashes, adversely affecting performance. Therefore, this mode is not recommended for high concurrency.

NIO (New I/O) solution

The NIO communication model is shown below

NIO is a synchronous non-blocking I/O model. The NIO framework was introduced in Java 1.4, corresponding to the Java.niO package, which provides abstractions such as channels, selectors, and buffers.

N in NIO can be interpreted as non-blocking, not just New. It supports buffer-oriented, channel-based approaches to I/O operations. NIO provides two different Socket channel implementations, SocketChannel and ServerSocketChannel, that correspond to Socket and ServerSocket in the traditional BIO model. Both channels support both blocking and non-blocking modes. Blocking mode, like traditional support, is relatively simple, but has poor performance and reliability. Non-blocking mode is the opposite. For low-load, low-concurrency applications, synchronous blocking I/O can be used for faster development and better maintenance; For high-load, high-concurrency (network) applications, NIO’s non-blocking mode should be used for development.

The NIO server

NIOServer.java

package com.easy.javaBio; import lombok.extern.slf4j.Slf4j; import java.io.IOException; import java.net.InetAddress; import java.net.InetSocketAddress; import java.net.Socket; import java.net.SocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.*; @Slf4j public class NIOServer { private InetAddress addr; private int port; private Selector selector; private static int BUFF_SIZE = 1024; public NIOServer(InetAddress addr, int port) throws IOException { this.addr = addr; this.port = port; startServer(); } private void startServer() throws IOException {// Get selector and channel (socketChannel) this.selector = selector. Open (); ServerSocketChannel serverChannel = ServerSocketChannel.open(); serverChannel.configureBlocking(false); ListenAddr = new InetSocketAddress(this.addr, this.port); // listenAddr = new InetSocketAddress(this.addr, this.port); serverChannel.socket().bind(listenAddr); serverChannel.register(this.selector, SelectionKey.OP_ACCEPT); Log.info ("NIOServer running... Press Ctrl-C to stop service "); While (true) {log.info(" Server waits for new connection and selector..." ); this.selector.select(); / / select key work Iterator keys = this. The selector. The selectedKeys (). The Iterator (); while (keys.hasNext()) { SelectionKey key = (SelectionKey) keys.next(); Key.remove (); // Skip if (! key.isValid()) { continue; } if (key.isAcceptable()) { this.accept(key); } else if (key.isReadable()) { this.read(key); } else if (key.isWritable()) { this.write(key); } else if (key.isConnectable()) { this.connect(key); } } } } private void connect(SelectionKey key) throws IOException { SocketChannel channel = (SocketChannel) key.channel(); If (channel.finishConnect()) {// successful log.info(" successful connection "); } else {// failed log.info(" failed connection "); } } private void accept(SelectionKey key) throws IOException { ServerSocketChannel serverChannel = (ServerSocketChannel)  key.channel(); SocketChannel channel = serverChannel.accept(); channel.configureBlocking(false); channel.register(this.selector, SelectionKey.OP_READ); Socket socket = channel.socket(); SocketAddress remoteAddr = socket.getRemoteSocketAddress(); Log.info (" Connect to: "+ remoteAddr); } private void read(SelectionKey key) throws IOException { SocketChannel channel = (SocketChannel) key.channel(); ByteBuffer buffer = ByteBuffer.allocate(BUFF_SIZE); int numRead = channel.read(buffer); If (numRead == -1) {log.info(" close client connection: "+ channel.socket().getremotesocketAddress ()); channel.close(); return; } String msg = new String(buffer.array()).trim(); Log.info (" get: "+ MSG); String reMsg = MSG + "+ system.currentTimemillis (); channel.write(ByteBuffer.wrap(reMsg.getBytes())); } private void write(SelectionKey key) throws IOException { ByteBuffer byteBuffer = ByteBuffer.allocate(BUFF_SIZE); byteBuffer.flip(); SocketChannel clientChannel = (SocketChannel) key.channel(); while (byteBuffer.hasRemaining()) { clientChannel.write(byteBuffer); } byteBuffer.compact(); } public static void main(String[] args) throws IOException { new NIOServer(null, 10002); }}Copy the code

With NIO, you can use Selector to finally determine which set of registered sockets are ready to perform I/O

NIO client

NIOClient.java

package com.easy.javaBio; import lombok.extern.slf4j.Slf4j; import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SocketChannel; import java.util.ArrayList; @Slf4j public class NIOClient { private static int BUFF_SIZE = 1024; public static void main(String[] args) throws IOException, InterruptedException {InetSocketAddress socketAddress = new InetSocketAddress("0.0.0.0", 10002); SocketChannel socketChannel = SocketChannel.open(socketAddress); Log.info (" Connect to BIOServer service, port: 10002...") ); ArrayList<String> companyDetails = new ArrayList<>(); Companydetails.add (" Tencent "); Companydetails.add (" Alibaba "); CompanyDetails. Add (" jingdong "); CompanyDetails. Add (" baidu "); companyDetails.add("google"); for (String companyName : companyDetails) { socketChannel.write(ByteBuffer.wrap(companyName.getBytes())); Log.info (" send: "+ companyName); ByteBuffer buffer = ByteBuffer.allocate(BUFF_SIZE); buffer.clear(); socketChannel.read(buffer); String result = new String(buffer.array()).trim(); Log.info (" received NIOServer reply message: "+ result); // Wait 2 seconds before sending the next message thread.sleep (2000); } socketChannel.close(); }}Copy the code

Run the example

Run our NIOServer first, then NIOClient, and watch the console output

NIOServer console output

17:35:40. [the main] INFO 921 com. Easy. In the operation of the javaBio. NIOServer - NIOServer... Press ctrl-c to stop service 17:35:40. 924. [the main] INFO com. Easy. JavaBio. NIOServer - server waiting for new connections and the selector to choose... 17:36:29. [the main] INFO 188 com. Easy. JavaBio. NIOServer - connect to: / 192.168.9.110:64443 17:36:29. 188 [main] INFO com. Easy. JavaBio. NIOServer - server waiting for new connections and the selector to choose... 17:36:29. [the main] INFO 194 com. Easy. JavaBio. NIOServer - got: Tencent 17:36:29. [the main] INFO 194 com. Easy. JavaBio. NIOServer - server waiting for new connections and the selector to choose... 17:36:31. [the main] INFO 194 com. Easy. JavaBio. NIOServer - got: Alibaba 17:36:31. [the main] INFO 195 com. Easy. JavaBio. NIOServer - server waiting for new connections and the selector to choose... 17:36:33. [the main] INFO 195 com. Easy. JavaBio. NIOServer - got: Jingdong 17:36:33. [the main] INFO 195 com. Easy. JavaBio. NIOServer - server waiting for new connections and the selector to choose... 17:36:35. [the main] INFO 196 com. Easy. JavaBio. NIOServer - got: Baidu 17:36:35. [the main] INFO 197 com. Easy. JavaBio. NIOServer - server waiting for new connections and the selector to choose... 17:36:37. [the main] INFO 197 com. Easy. JavaBio. NIOServer - got: Google 17:36:37. [the main] INFO 198 com. Easy. JavaBio. NIOServer - server waiting for new connections and the selector to choose... 17:36:39. [the main] INFO 198 com. Easy. JavaBio. NIOServer - close the client connection: / 192.168.9.110:64443 17:36:39. 198 [main] INFO com. Easy. JavaBio. NIOServer - server waiting for new connections and the selector to choose...Copy the code

NIOClient console output

17:36:29. [the main] INFO 189 com. Easy. JavaBio. BIOServer NIOClient - connection service, port: 10002... 17:36:29. [the main] INFO 194 com. Easy. JavaBio. NIOClient - send: Tencent 17:36:29. [the main] INFO 194 com. Easy. JavaBio. NIOClient - receive NIOServer reply messages: Tencent: hello, this is BIOServer give you a reply message: 1576229789194 17:36:31. 194 [main] INFO com. Easy. JavaBio. NIOClient - send: Alibaba 17:36:31. [the main] INFO 195 com. Easy. JavaBio. NIOClient - receive NIOServer reply messages: Alibaba, how are you, this is BIOServer give you a reply message: 1576229791194 17:36:33. 195 [main] INFO com. Easy. JavaBio. NIOClient - send: Jingdong 17:36:33. [the main] INFO 196 com. Easy. JavaBio. NIOClient - receive NIOServer reply messages: Jingdong: hello, this is BIOServer give you a reply message: 1576229793195 17:36:35. 196 [main] INFO com. Easy. JavaBio. NIOClient - send: Baidu 17:36:35. [the main] INFO 197 com. Easy. JavaBio. NIOClient - receive NIOServer reply messages: Baidu hi, this is BIOServer give you a reply message: 1576229795197 17:36:37. 197 [main] INFO com. Easy. JavaBio. NIOClient - send: Google 17:36:37. [the main] INFO 198 com. Easy. JavaBio. NIOClient - receive NIOServer reply messages: Google: hello, this is BIOServer give you a reply message: 1576229797198Copy the code

The NIO server receives requests from the client every two seconds and responds to messages from the client.

It is possible to build applications directly using the Java NIO API, but it is not easy to get it right and secure. Especially under high loads, reliably and efficiently processing and scheduling I/O operations is a tedious and error-prone task. You can select high-performance network programming frameworks such as Netty and Apache Mina.

Netty builds NIO communication service solutions

Using the JDK native Web application API, there are problems

  • NIO class libraries and apis are cumbersome to use, you need to master Selector, ServerSocketChannel, SocketChannel, ByteBuffer, etc
  • Additional skills are required, such as familiarity with Java multithreaded programming. Since NIO programming involves the Reactor model, you must be familiar with multithreaded and network programming in order to write high quality NIO programs
  • The reliability of the ability to complement, the workload and difficulty of development are very large. For example, the client is faced with disconnection and reconnection, network intermittent disconnection, half-packet read and write, failure cache, network congestion and abnormal code stream processing, etc. NIO programming is characterized by relatively easy function development, but the workload and difficulty of reliability capability complement are very large

Netty on the JDK built-in NIO API encapsulation, to solve the above problems, the main features are

  • High concurrency

Netty is a network communication framework based on NIO (Nonblocking I/O). Compared with BIO (Blocking I/O), its concurrency performance is greatly improved.

  • Transmission is fast

Netty’s speed depends on NIO’s zero-copy feature.

  • Good packaging

Netty encapsulates many of the details of NIO operations and provides an easy-to-use API.

Advantages of the Netty framework

  • API simple to use, low development threshold;
  • Powerful, preset a variety of encoding and decoding functions, support a variety of mainstream protocols;
  • With strong customization capability, the communication framework can be flexibly extended through ChannelHandler.
  • High performance. Compared with other mainstream NIO frameworks in the industry, Netty has the best overall performance.
  • Mature and stable, Netty has fixed all the JDK NIO bugs it has found, and business developers no longer need to worry about NIO bugs;
  • Active community, short version iteration cycle, found bugs can be fixed in time, at the same time, more new features will be added;
  • Experienced large-scale commercial application test, quality has been verified. It has been successfully used in Internet, big data, online games, enterprise applications, telecom software and many other industries, proving that it has been fully able to meet the commercial applications of different industries.

Code implementation

Pom. XML dependency

<? The XML version = "1.0" encoding = "utf-8"? > < project XMLNS = "http://maven.apache.org/POM/4.0.0" XMLNS: xsi = "http://www.w3.org/2001/XMLSchema-instance" Xsi: schemaLocation = "http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd" > < modelVersion > 4.0.0 < / modelVersion > < the parent > < groupId > org. Springframework. Boot < / groupId > The < artifactId > spring - the boot - starter - parent < / artifactId > < version > 2.1.9. RELEASE < / version > < relativePath / > <! -- lookup parent from repository --> </parent> <groupId>com.easy</groupId> <artifactId>netty</artifactId> <version>0.0.1</version> <name> Netty </name> <description>Demo project for Spring Boot</description> <properties> < Java version > 1.8 < / Java version > < encoding > utf-8 < / encoding > <project.build.sourceEncoding>UTF-8</project.build.sourceEncoding> <project.reporting.outputEncoding>UTF-8</project.reporting.outputEncoding> </properties> <dependencies> <! -- https://mvnrepository.com/artifact/io.netty/netty-all --> <dependency> <groupId>io.netty</groupId> < artifactId > netty -all < / artifactId > < version > 4.1.43. The Final < / version > < / dependency > < the dependency > <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> <scope>test</scope> </dependency> <dependency> <groupId>org.projectlombok</groupId> <artifactId>lombok</artifactId> <scope>compile</scope> </dependency> </dependencies> <modules> <module>java-tcp</module> <module>netty-server</module> <module>netty-client</module> </modules> <build> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build> </project>Copy the code

Set up the Netty server

NettyServer.java

package com.easy.nettyServer; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import javax.annotation.PreDestroy; import java.net.InetSocketAddress; @component @slf4j public class NettyServer {/** * boss thread group for handling connections */ private EventLoopGroup boss = new NioEventLoopGroup(); /** * private EventLoopGroup work = new NioEventLoopGroup(); @Value("${netty.port}") private Integer port; /** * Start Netty Server ** @throws InterruptedException */ @postconstruct public void start() throws InterruptedException { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(boss, Work) / / specified Channel. The Channel (NioServerSocketChannel. Class) / / use the designated port setting socket address. LocalAddress (new InetSocketAddress (port)) Option (channeloption.so_backlog, 1024) // Set the TCP long connection. Generally, if there is no data communication within two hours,TCP automatically sends an active probe data message. ChildOption (channeloption.so_keepalive, // Wrap small packets into larger frames for transmission, Increase network load. ChildOption (channeloption.tcp_nodelay, true). ChildHandler (new ServerChannelInitializer()); ChannelFuture future = bootstrap.bind().sync(); If (future.isSuccess()) {log.info(" Start Netty Server"); } } @PreDestroy public void destory() throws InterruptedException { boss.shutdownGracefully().sync(); work.shutdownGracefully().sync(); The info (" Netty off "); }}Copy the code

NettyServerHandler.java

package com.easy.nettyServer; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import lombok.extern.slf4j.Slf4j; @ Slf4j public class NettyServerHandler extends ChannelInboundHandlerAdapter {/ * * * client connection will trigger * / @ Override public void channelActive(ChannelHandlerContext ctx) throws Exception { log.info("Channel active......" ); } /** * Override public void channelRead(ChannelHandlerContext CTX, Object MSG) throws Exception {log.info(" Server received message: {}", msg.toString()); Ctx. write(" This is the server, I got your message!" ); ctx.flush(); } /** * Override public void exceptionCaught(ChannelHandlerContext CTX, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}Copy the code

ServerChannelInitializer.java

package com.easy.nettyServer; import io.netty.channel.ChannelInitializer; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; import io.netty.util.CharsetUtil; public class ServerChannelInitializer extends ChannelInitializer<SocketChannel> { @Override protected void InitChannel (SocketChannel SocketChannel) throws Exception {// Add codec socketchannel.pipeline ().addlast ("decoder", new StringDecoder(CharsetUtil.UTF_8)); socketChannel.pipeline().addLast("encoder", new StringEncoder(CharsetUtil.UTF_8)); socketChannel.pipeline().addLast(new NettyServerHandler()); }}Copy the code

Example Creating a Netty client

NettyClient.java

package com.easy.nettyClient; import io.netty.bootstrap.Bootstrap; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.SocketChannel; import io.netty.channel.socket.nio.NioSocketChannel; import lombok.extern.slf4j.Slf4j; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Component; import javax.annotation.PostConstruct; import java.util.concurrent.TimeUnit; @Component @Slf4j public class NettyClient { private EventLoopGroup group = new NioEventLoopGroup(); @Value("${netty.port}") private Integer port; @Value("${netty.host}") private String host; private SocketChannel socketChannel; / * * * send messages * / public void sendMsg (String MSG) {socketChannel. WriteAndFlush (MSG); } @PostConstruct public void start() { Bootstrap bootstrap = new Bootstrap(); bootstrap.group(group) .channel(NioSocketChannel.class) .remoteAddress(host, port) .option(ChannelOption.SO_KEEPALIVE, true) .option(ChannelOption.TCP_NODELAY, true) .handler(new NettyClientInitializer()); ChannelFuture future = bootstrap.connect(); Future1 -> {if (future1.isSuccess()) {log.info(" Netty server successfully connected ");  } else {log.info(" Connection failed, retry disconnection "); future1.channel().eventLoop().schedule(() -> start(), 20, TimeUnit.SECONDS); }}); socketChannel = (SocketChannel) future.channel(); }}Copy the code

NettyClientHandler.java

package com.easy.nettyClient; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInboundHandlerAdapter; import lombok.extern.slf4j.Slf4j; @Slf4j public class NettyClientHandler extends ChannelInboundHandlerAdapter { @Override public void ChannelActive (ChannelHandlerContext CTX) throws Exception {log.info(" Client Active....." ); } @override public void channelRead(ChannelHandlerContext CTX, Object MSG) throws Exception {log.info(" The client receives the message: {}", msg.toString()); } @Override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); }}Copy the code

NettyClientInitializer.java

package com.easy.nettyClient; import io.netty.channel.ChannelInitializer; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; public class NettyClientInitializer extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast("decoder", new StringDecoder()); socketChannel.pipeline().addLast("encoder", new StringEncoder()); socketChannel.pipeline().addLast(new NettyClientHandler()); }}Copy the code

Run the example

Open a browser, the address bar: http://localhost:8091/send? MSG =%E4%BD%A0%E5%A5%BD, observe the server and client console

Server console output

The 2019-12-13 18:01:37. 11288-901 the INFO [the main] com.easy.nettyServer.Net tyServer: Start the Netty Server 2019-12-13 18:01:45. 11288-834 the INFO] [ntLoopGroup - 3-1 com.easy.nettyServer.Net tyServerHandler: Channel active...... The 2019-12-13 18:02:07. 11288-858 the INFO [ntLoopGroup - 3-1] com.easy.nettyServer.Net tyServerHandler: server receives the message: helloCopy the code

Client console output

18:01:45 2019-12-13. 11908-822 the INFO [ntLoopGroup - 2-1] com.easy.nettyClient.Net tyClient: Connection Netty server successful 18:01:45 2019-12-13. 11908-822 the INFO] [ntLoopGroup - 2-1 com.easy.nettyClient.Net tyClientHandler: Client Active..... The 2019-12-13 18:02:08. 11908-005 the INFO [ntLoopGroup - 2-1] com.easy.nettyClient.Net tyClientHandler: the client receives the message: This is the server. I got your message!Copy the code

Netty is used to implement our NIO communication

Netty module component

The Bootstrap, ServerBootstrap

A Netty application usually starts with a Bootstrap, which is used to configure the entire Netty program and connect various components. In Netty, Bootstrap is the Bootstrap class of the client program, and ServerBootstrap is the Bootstrap class of the server.

The Future, ChannelFuture

In Netty, all IO operations are asynchronous. You can’t immediately know if a message is being handled correctly, but you can either wait for it to complete or register a listener. A listener automatically triggers a registered listener event when the operation succeeds or fails.

Channel

Netty A network communication component used to perform network I/O operations. Channel provides users with:

  • The status of the channel currently connected to the network (for example, open? Is it connected?
  • Configuration parameters for the network connection (such as receive buffer size)
  • Provides asynchronous network I/O operations (such as establishing connections, reading and writing, binding ports). Asynchronous calls mean that any I/O calls are returned immediately and there is no guarantee that the requested I/O operation has been completed at the end of the call. The call immediately returns an instance of ChannelFuture, and by registering listeners on ChannelFuture, the caller can be notified of a successful, failed, or canceled I/O callback.
  • Supports associated I/O operations with corresponding handlers

Different types of channels correspond to connections of different protocols and blocking types. The following are some common Channel types

  • NioSocketChannel, asynchronous client TCP Socket connection
  • NioServerSocketChannel, an asynchronous server TCP Socket connection
  • NioDatagramChannel, asynchronous UDP connection
  • NioSctpChannel, asynchronous client Sctp connection
  • NioSctpServerChannel, asynchronous Sctp server side connection

Selector

Netty implements I/O multiplexing based on a Selector object. With a Selector, a thread can listen for multiple connected Channel events. After registering a Channel in a Selector, The Selector mechanism can automatically and continuously query the registered channels for ready I/O events (such as readable, writable, network connection completed, etc.), making it easy for the program to efficiently manage multiple channels with a single thread

NioEventLoop

NioEventLoop maintains a thread and task queue, which supports asynchronous submission of tasks. When the thread is started, NioEventLoop’s RUN method is called to execute I/O tasks and non-I /O tasks:

  • I/O tasks are the ready events in selectionKey, such as Accept, Connect, read, write, and so on, triggered by processSelectedKeys.
  • Non-io tasks Tasks that are added to a taskQueue, such as register0 and bind0, are triggered by the runAllTasks method.

The execution time ratio of the two tasks is controlled by ioRatio. The default value is 50, indicating that the time allowed for non-I/O tasks is the same as that for I/O tasks.

NioEventLoopGroup

NioEventLoopGroup, which manages the life cycle of eventLoop, can be understood as a thread pool. It maintains a group of threads internally. Each thread (NioEventLoop) is responsible for processing events on multiple channels, and a Channel corresponds to only one thread.

ChannelHandler

ChannelHandler is an interface that processes I/O events or intercepts I/O operations and forwards them to the next handler in its ChannelPipeline(business processing chain).

ChannelHandlerContext

Saves all context information associated with a Channel, along with a ChannelHandler object

ChannelPipline

Saves a List of ChannelHandlers that handle or intercept inbound events and outbound operations for a Channel. ChannelPipeline implements an advanced form of intercepting filter pattern that gives the user complete control over how events are handled and how the various Channelhandlers in a Channel interact with each other.

data

  • Netty example source code
  • Netty’s official website
  • reference

Spring Boot and Cloud learning projects