Introduction to the

  • BIO: Synchronous blocking I/O, which is implemented in a one-thread connection mode. When the client has a connection request, the server needs to start a thread to process it. If the connection does not do anything, it will cause unnecessary thread overhead, which can be improved by thread pool mechanism.
  • NIO: Synchronous non-blocking I/O. The server implements one request per thread, that is, all connection requests sent by the client are registered with the multiplexer. The multiplexer polls the connection to have I/O requests and starts a thread to process them.
  • Netty is an asynchronous event-driven network application framework for rapid development of high-performance, highly reliable network server and client programs. Netty simplifies network application development and is a technology used by many frameworks and companies. Netty wasn’t born out of nothing. It was an evolution of BIO, NIO, and AIO, a NIO framework.

BIO

  • The basic model of network programming is the C/S model, that is, communication between two processes.
  • The server provides the IP address and monitoring port. The client initiates a connection request to the address monitored by the server through the connection operation. The client initiates a connection request through the three-way handshake.
  • In the traditional synchronous blocking model, ServerSocket is responsible for binding IP addresses and starting listening ports. The Socket initiates the connection. After the connection is successful, the two sides communicate synchronously blocking through input and output streams.

The model of the biggest problems is the lack of elastic expansion ability, when the client after concurrent increased traffic, number number of concurrent access to the client and server thread is 1:1 proportion relations, in Java thread is valuable system resources, the rapid expansion of number of threads, after a sharp decline in the performance of the system will be, as the traffic continued to increase, the system eventually failed. This communication model is not applicable in high concurrency scenarios. ** Synchronous blocking BIO to create a Server source ** :Copy the code
package com.scoket.bio;

import java.io.IOException;
import java.net.ServerSocket;
import java.net.Socket;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class BIOServer {
    public static void main(String[] args) throws IOException {
        ExecutorService executor = Executors.newFixedThreadPool(3);
        RequestHandler requestHandler = new RequestHandler();
        try(ServerSocket serverSocket = new ServerSocket(8888)){
            System.out.println("BIOServer has started,listenning on port: "+serverSocket.getLocalSocketAddress());
            // Multiple clients request connections
            while (true) {
                Socket clientSocket = serverSocket.accept();
                System.out.println("Connection from" + clientSocket.getRemoteSocketAddress());
                // To allow the thread pool to execute the task
                executor.submit(newClientHandler(clientSocket,requestHandler)); }}}}Copy the code

Synchronous blocking BIO create Client

package com.scoket.bio;

import java.io.IOException;

import java.net.Socket;
import java.util.Scanner;

public class ClientHandler implements Runnable {
    private final Socket clientSocket;
    private final RequestHandler requestHandler;

    public ClientHandler(Socket clientSocket, RequestHandler requestHandler) {
        this.clientSocket = clientSocket;
        this.requestHandler = requestHandler;
    }
    @Override
    public void run(a) {
        try (Scanner input = new Scanner(clientSocket.getInputStream())) {
            // Unlimited interaction for each request
            while (true) {
                // The real cause of the block is the point where the thread is delayed while waiting for input from the client
                String request = input.nextLine();
                if ("quit".equals(request)) {
                    break; } System.out.println(request); String response = requestHandler.handler(request); clientSocket.getOutputStream().write(response.getBytes()); }}catch (IOException e){
            throw newRuntimeException(e); }}}Copy the code

Synchronous blocking BIO creates RequestHandler

package com.scoket.bio;

public class RequestHandler {
    public String handler(String request){
        return "From BIOServer Hello" + request + "\n"; }}Copy the code

NIO

  • NIO provides two different Socket channel implementations, SocketChannel and ServerSocketChannel, that correspond to Socket and ServerSocket in the traditional BIO model.
  • The two new 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.
  • NIO programming is channel-oriented (BIO is stream-oriented). Streams are write/write and are one-way, meaning channels can be read and written in both directions. All of NIO’s channel-based apis operate on data indirectly through the operation buffer ByteBuffer
  • In: Disk — channel — > ByteBuffer — > Data (memory)
  • Out: Data (memory) –> ByteBuffer –> channel –> disk

NIO programming involves ServerSocketChannel, SocketChannel, ByteBuffer, Selector

Synchronous non-blocking NIO creation server source code:

package com.scoket.nio;

import com.scoket.bio.RequestHandler;
import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.*;
import java.util.Iterator;
import java.util.Set;


public class NIOServer {
    // Channel[Server Client], Selector, Buffer
    public static void main(String[] args) throws IOException {
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.configureBlocking(false);
        serverSocketChannel.bind(new InetSocketAddress(9999));
        System.out.println("NIOServer has started,listening on port: "+serverSocketChannel.getLocalAddress());
        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
        ByteBuffer buffer = ByteBuffer.allocate(1024);
        RequestHandler requestHandler = new RequestHandler();
        while (true) {int select = selector.select();
            if (select == 0) {continue;
            }
            Set<SelectionKey> selectionKeys = selector.selectedKeys();
            Iterator<SelectionKey> iterator = selectionKeys.iterator();
            while (iterator.hasNext()){
                // Handle connection operations for each client
                SelectionKey key = iterator.next();
                if (key.isAcceptable()){
                    ServerSocketChannel channel = (ServerSocketChannel) key.channel();
                    SocketChannel clientChannel = channel.accept();
                    System.out.println("Connection from: "+clientChannel.getRemoteAddress());
                    clientChannel.configureBlocking(false);
                    clientChannel.register(selector,SelectionKey.OP_READ);
                }
                if (key.isReadable()){
                    SocketChannel channel = (SocketChannel) key.channel();
                    channel.read(buffer);
                    String request = new String(buffer.array()).trim();
                    buffer.clear();
                    System.out.println(String.format("From %s : %s",channel.getRemoteAddress(),request)); String response = requestHandler.handler(request); channel.write(ByteBuffer.wrap(response.getBytes())); } iterator.remove();; }}}}Copy the code

Netty

  • Netty communication channel: Through THE AOP programming thought (responsibility chain design pattern), the realization of message encoding and decoding.

    SBT =new ServerBootstrap(); 2) create an EventLoopGroup boss and worker. 3) associate boss and worker> sbt.group(boss,worker); 4) Set ServerSocketChannel implementation class SBT. channel(NioServerSocketChannel); 5) Initialize channel sbt.childHandler(initialize channel); ChannelFuture =sbt.bind(port).sync(); ChannelFuture =sbt.bind(port).sync(); Future.channel ().closeFuture().sync(); 10) Throwing thread resources into the environment where the worker # shutdownexceptionexceptionexception () occurs;

Netty create client source code:

package com.cherry.socket.netty.client;
import io.netty.bootstrap.Bootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.nio.NioSocketChannel;

public class ClientBootStrap {
    public static void main(String[] args) throws InterruptedException {
        //1.Create Bootstrap
        Bootstrap bt = new Bootstrap();
        //2.Create thread pool(worker)
        EventLoopGroup worker = new NioEventLoopGroup();
        //3. Associate the thread pool
        bt.group(worker);
        //4.Set up the client
        bt.channel(NioSocketChannel.class);
        //5.Initialize the communication channel (key point)
        bt.handler(new ClientChannelInitializer());
        / / 6. Connections
        ChannelFuture channelFuture = bt.connect("127.0.0.1".9999).sync();
        //7.Wait for the server to close
        channelFuture.channel().closeFuture().sync();
        //8.release the resourceworker.shutdownGracefully(); }}Copy the code
package com.cherry.socket.netty.client;
import io.netty.buffer.ByteBuf;
import io.netty.buffer.Unpooled;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;
import io.netty.util.CharsetUtil;
import javax.xml.transform.Source;

public class ClientChannelHander extends ChannelHandlerAdapter {
    /* Catch an exception in the transmission of data in the channel */
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
        //super.exceptionCaught(ctx, cause);
        System.out.println("Error:"+cause.getMessage());
    }
    /* Receive data */
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
        //super.channelRead(ctx, msg);
        ByteBuf byteBuf = (ByteBuf) msg;
        System.out.println(((ByteBuf)msg).toString(CharsetUtil.UTF_8));
    }
    /* Send data when connecting to the server */
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception {
        //super.channelActive(ctx);
        ByteBuf buf = Unpooled.buffer();
        buf.writeBytes("Hello, this is the client!".getBytes()); ctx.writeAndFlush(buf); }}Copy the code
package com.cherry.socket.netty.client;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelPipeline;
import io.netty.channel.socket.SocketChannel;

public class ClientChannelInitializer extends ChannelInitializer<SocketChannel> {
    @Override
    protected void initChannel(SocketChannel socketChannel) throws Exception {
        //communication channel
        ChannelPipeline pipeline = socketChannel.pipeline();
        pipeline.addLast(newClientChannelHander()); }}Copy the code

Pom.xml used by BIO NIO Netty above

<! --> <dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>5.0. 0.Alpha2</version>
</dependency>
Copy the code

Through the analysis of Netty, we summarize its advantages as follows: 1. Simple API and low development threshold; 2. 2. Powerful, preset a lot of coding functions, support a variety of mainstream protocols; 3. With strong customization capability, the communication framework can be flexibly extended through ChannelHandler; 4. High performance. Compared with other mainstream NIO frameworks, Netty has the best overall performance; 5. Mature and stable, Netty has fixed all JDK NIO bugs that have been found, and business developers do not need to worry about NIO bugs any more; 6. Active community, short version iteration cycle; 7. After large-scale commercial application test, the quality has been verified. Netty has been successfully commercialized in Internet, big data, online games, enterprise applications, telecom software and many other fields, and it has proved that it can fully meet the needs of business applications in different industries.