introduce

Netty’s HTTP stack performs well both in terms of performance and reliability, making it ideal for non-Web container applications. Compared with traditional Tomcat, Jetty and other Web containers, Netty’s HTTP stack is lighter and smaller, and has good flexibility and customization. Let’s take a look at Netty’s core API and manually implement two features to build a deeper understanding.

buffer

It interacts with a Channel. Data is read from a Channel into the buffer and written from the buffer to a Channel

flip()

This method reverses the buffer, gives position to limit, and sets position to 0.

clear()

Clear this buffer, set position to 0, and give the value of Capacity to limit

rewind()

Rewind this buffer and set position to 0

directByteBuffer

Can reduce one copy from system space to user space. However, buffers are more expensive to create and destroy and are out of control, often using memory pools to improve performance. Direct buffers are primarily allocated to large and persistent buffers that are vulnerable to native I/O operations on the underlying system. For small and medium applications with small data volumes, heapBuffer can be used to be managed by the JVM.

channel()

Represents an OPEN connection between the I/O source and the target, which is bidirectional but does not directly access data, only interacts with Buffer. The FileChannel read method and the FileChannel write method both cause data to be copied twice.

selector

A single thread can manage multiple channels

  • The open method creates a Selector
  • The register method registers a channel with the multiplexer. It can be used to listen for events (including read, write, connect, accept). After registering events, a SelectionKey is generated. It represents the registration relationship between a SelectableChannel and a Selector.
  • Wakeup method: returns the first selection operation that has not been returned immediately. Wake up is because a new Channel is registered or the event Channel is closed and unregistered. (Higher priority events are triggered, such as timer events, which are expected to be handled in a timely manner)
The role of the selector

The implementation class of Selector in Linux is EPollSelectorImpl, which delegates to the EPollArrayWrapper implementation. The three native methods are wrappers of epoll. And EpollSelectorImpl. Register method, by calling the epoll_ctl registered event, with the epoll instances will also register file descriptor (fd) added to the corresponding relationship between the SelectionKey fdToKey, This map maintains the mapping of file descriptors to selectionkeys. The fdToKey can sometimes become very large because there are so many channels registered with the Selector (millions of connections) that expired or expired channels are not closed in time. The fdToKey is always read serially, and reading is done in the SELECT method, which is non-thread-safe.

pipe

One-way data connection between two threads. Data will be written to the sink channel and read from the source channel.

The functional requirements

  1. The Netty server listens on port 8080
  2. The browser sends the request “http://localhost:8080/”
  1. The server can reply to the client with a message “Hello! “I’m a Netty server” and filters for specific requested resources

implementation

Public class NettyHttpServer {private int port; public NettyHttpServer(int port) { this.port = port; } public void run() throws InterruptedException { //1. Create a bossGroup thread group: handle network events -- connection events EventLoopGroup bossGroup = NULL; 2* Number of processor threads EventLoopGroup workerGroup = null; try { bossGroup = new NioEventLoopGroup(1); workerGroup = new NioEventLoopGroup(); ServerBootstrap ServerBootstrap = new ServerBootstrap(); Serverbootstrap. group(bossGroup, workerGroup, serverbootstrap. group) workerGroup) .channel(NioServerSocketChannel.class) //5. Option (channeloption.so_backlog, 128)//6. Parameter Settings. ChildOption (channeloption.so_keepalive, Boolean.TRUE)//6. ChildHandler (new ChannelInitializer<SocketChannel>() {//7. Override protected void initChannel(SocketChannel ch) throws Exception {//8. // Add codec ch.pipeline().addLast(new HttpServerCodec()); // Add custom business handling class ch.pipeline().addLast(new NettyHTTPServerHandler()); }}); ChannelFuture Future = serverbootstrap. bind(port); //9. future.addListener(new ChannelFutureListener() { @Override public void operationComplete(ChannelFuture future) throws Exception {if (future.isSuccess()) {system.out.println (" Port binding succeeded! ); } else {system.out. println(" Port binding failed!" ); }}}); System.out.println("HTTP server started successfully."); //10. Close the channel(not really close, but listen for the closed channel) and close the connection pool future.channel(). } finally { bossGroup.shutdownGracefully(); workerGroup.shutdownGracefully(); } } public static void main(String[] args) throws InterruptedException { new NettyHttpServer(8080).run(); }} public class NettyHTTPServerHandler extends SimpleChannelInboundHandler < HttpObject > {/ * * * * @ param CTX * read ready event @param msg * @throws Exception */ @Override protected void channelRead0(ChannelHandlerContext ctx, Throws Exception {// Check whether the request is an HTTP request. If (MSG instanceof HttpRequest){DefaultHttpRequest request = (DefaultHttpRequest) msg; System.out.println(" browser request path :"+request.uri()); If ("/favicon.ico".equals(request.uri())){system.out.println (" icon does not respond "); return; } ByteBuf ByteBuf = Unpooled. CopiedBuffer ("Hello! I'm a Netty server ", charsetutil.utf_8); DefaultHttpResponse response = new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.OK, byteBuf); // Set response.headers(). Set (httpheadernames.content_type,"text/ HTML; charset=utf-8").set(HttpHeaderNames.CONTENT_LENGTH,byteBuf.readableBytes()); ctx.writeAndFlush(response); }}}Copy the code

Based on Netty WebSocket development web version chat room

WebSocket is introduced

WebSocket is a protocol for full duplex communication over a single TCP connection. It makes it easier to exchange data between the client and the server, allowing the server to actively push data to the client. In the WebSocket API, the client and server only need to complete a handshake to directly create a persistent connection and two-way data transfer. WebSocket application scenarios are very wide:

  1. Social subscription
  2. Co-editing/programming
  3. Stock fund quotation
  4. Sports Live update
  5. Multimedia chat
  6. online education

Differences between WebSocket and HTTP

HTTP protocol is used in the application layer protocol, it is based on TCP protocol, HTTP protocol to establish a connection must have three handshakes to send information. HTTP connections are classified into short and long connections. Short links require three handshakes per request to send their message. Each request corresponds to a response. A long connection keeps TCP connections open within a certain period of time. Communication between the client and the server must be initiated by the client and then returned by the server. The client is active, the server is passive. The client must continuously send long connections to the server in order to obtain real-time messages from the server.

WebSocket implements multiplexing, which is full duplex communication. Under the WebSocket protocol, the server and client can send messages at the same time. After a WebSocket connection is established, the server can actively send messages to the client. And the message does not have to be part of the message with the HEAD to communicate with HTTP long links, this way, not only reduces the server pressure. And the information is also reduced some of the redundant information.