A preface.
Before introducing NIO core components, let’s take a look at the common socket programming client and server modes.
1.1 the service side
1.1.2 Server Server Entry
import java.io.IOException; import java.net.ServerSocket; import java.net.Socket; public class Server { private ServerSocket SERVER=null; private Integer PORT; public Server(int port){ this.PORT=port; try { SERVER=new ServerSocket(port); } catch (IOException e) { e.printStackTrace(); Throws Exception public void doStart()throws Exception{// The asynchronous thread obtains the client socket connection. New Thread(()->{while (true){try {// Wait for a new connection to connect to the client socket socket= server.accept (); System.out.println(" new client added "); // Handle new connections new ClientHandler(socket).dostart (); } catch (Exception e) { e.printStackTrace(); } } }).start(); } public static void main(String[] args) throws Exception{ Server server=new Server(8001); server.doStart(); System.out.println(" Server started."); }}Copy the code
1.1.2 Server-side message processing classes
import java.io.InputStream; import java.net.Socket; /** * public class ClientHandler {private Socket Socket; @param socket */ public ClientHandler(socket socket) {this.socket=socket; @throws Exception */ public void doStart() {new Thread(()->{try { / / read the client input stream InputStream InputStream. = this socket. The getInputStream (); While (true) {// Specify the summary length read byte[] maxData = new byte[1024]; int len; While (len = inputStream.read(maxData))! = -1) { String message = new String(maxData, 0, len); System.out.println(" client sends message: "+ message); // Return message socket.getOutputStream().write(maxData); } } } catch (Exception e) { e.printStackTrace(); } }).start(); }}Copy the code
1.2 Client Connection or Telnet Command Connection
1.2.1 Client Socket Connection
import java.io.IOException; import java.net.Socket; import java.util.concurrent.TimeUnit; /** * client */ public class Client { private Socket socket; Public void start(){new Thread(()->{try {// Connect to specified port socket=new socket ("127.0.0.1",8001); int i=0; While (true) {socket.getoutputstream ().write((" hello, I am a client "+i++).getbytes ()); TimeUnit.SECONDS.sleep(1); } } catch (IOException e) { e.printStackTrace(); } catch (InterruptedException e) { e.printStackTrace(); } }).start(); } public static void main(String[] args)throws Exception {system.out.println (" The client is started "); new Client().start(); }}Copy the code
1.2.2 Telnet Connection Mode
Telnet 127.0.0.1 8001Copy the code
Summary of the process server and client processes above.
Server ->1. Set up the serverSocket server service. Bind the service port through the serverSocket constructor. Server ->2. Call the serverSocket Accept method and the current thread is blocked waiting for the client to connect to the client -> 3. The client establishes the socket connection by binding the socket constructor to specify the server port client ->4. 5. The server allocates a new thread to handle the client socket through the Accept method. Server ->6. The server asynchronously processes the socket stream through handler and sends the message back to the client.
The above is the use of traditional IO to handle the standard socket. From the above coding and summary process can be known. In step 5: The server creates a new thread for each client connection. This is also a feature of traditional IO processing IO, in the face of high concurrency in the scenario of continuous creation of threads is difficult to meet. So with that in mind we’re going to move on.
Netty core components
2.1 NioEventLoop
In traditional IO, we use asynchronous threads to handle client connections and client writing to the output stream. The corresponding component in Netty is the NioEventLoop loop class. Similar to the entire Netty Bootstrap role, so we often see the following in this way. The entire server-side Netty action is handled by declaring two NioEventloops.
EventLoopGroup bossGroup=new NioEventLoopGroup(); EventLoopGroup workerGroup=new NioEventLoopGroup(); ServerBootstrap =new ServerBootstrap(); serverBootstrap.group(bossGroup,workerGroup)Copy the code
The corresponding traditional IO is the following code bossGroup worker loop
2.2 the Channel
Both the serverSocket on the server and the socket on the client are exchanged around this socket object. The corresponding NIO is the Channel object. Netty provides several common channels through the low-level encapsulation of channels. The most common is NioServerSocketChannel. Continue to learn.
2.4 PipeLine&ChannelHandler
Netty defines the logical chain in the whole service processing process through PipeLine, which is similar to the chain processing in SpringMVC, and each logical code is ChannelHandler
2.5 Bytebuf
In traditional IO, we send client data and parse the data received by the server through simple input and output streams. The corresponding component in Netty is Bytebuf, which defines Netty’s own bytecode pattern.
Traditional Java serialization
- Byte streams take up too much space and burden resources
- Serialization performance consumes higher CPU resources
- Java serialized byte streams cannot be used across languages
3. Summary
Above we first understand the traditional IO socket under the common programming mode, understand the traditional IO server and client process. Then for each step we understand the corresponding process in Netty components corresponding to it, convenient for us to learn each component in the future can be better and the existing traditional IO methods to compare and use. Specific components: