One, foreword
1. What is netty?
High-performance, event-driven, asynchronous, non-clogging niO-BASED client, server side programming framework (NIO's framework) stability and scalabilityCopy the code
2.NET TY Usage scenarios.
High performance domain multi-threaded concurrent domain asynchronous communication domainCopy the code
3. Study the list
IO communication Netty introduction WebSocket Introduction Netty implementation WebSocket communication caseCopy the code
Java IO communication
Number of clients: BIO (1:1) Pseudo-asynchronous I/O (M :n) NIO (M :1) AIO (M :0) IO type: BIO (blocking synchronous I/O) Pseudo-asynchronous I/O (blocking synchronous I/O) NIO (non-blocking synchronous I/O) AIO (Non-blocking Asynchronous I/O) Bio (simple) Pseudo asynchronous IO (simple) NIO (complex) AIO (complex, but simpler than NIO) Debugging difficulty: ditto Reliability: BIO (bad) Pseudo asynchronous IO (bad) NIO (good) AIO (good) Throughput: dittoCopy the code
3. Introduction to netty
1. Defects of native NIO. Complex class libraries and apis; High threshold for entry; Workload and difficulty; JDK NIO has bug 2.NET TY advantage. API is simple; Low threshold of entry; High performance; Mature and stable.Copy the code
4. Introduction to websocket
1. What is WebSocket? H5 protocol specification; Handshake mechanism; Solve the client and server real-time communication technology. 2. Advantages of WebSocket? Save communication overhead; The server sends data to the client actively; Real-time communication; 3. Websocket establishes a connection. The client initiates a handshake request. The server responds to the request; The connection is established. 4. Websocket life cycle. Open the event; Message event; Error event; Close the event. 5. Websocket closes the connection. The server closes the underlying TCP connection. The client initiates TCP CLOSE. ProcedureCopy the code
Netty webSocket communication case.
1. Functions
Netty development server; HTML implementation client; Real-time interaction between the server and client.Copy the code
2. Code implementation
2.1 Global configuration of storage factories
package com.websocket.netty; import io.netty.channel.group.ChannelGroup; import io.netty.channel.group.DefaultChannelGroup; import io.netty.util.concurrent.GlobalEventExecutor; /** * @author lilinshen * @title * @description * @date 2018/5/23 10:32 */ public class NettyConfig { Public static ChannelGroup ChannelGroup = new static ChannelGroup = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE); }Copy the code
2.2 Core business processing class for processing/receiving/responding to WebSocket requests from clients
package com.websocket.netty; import io.netty.buffer.ByteBuf; import io.netty.buffer.Unpooled; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelFutureListener; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.handler.codec.http.DefaultFullHttpResponse; import io.netty.handler.codec.http.FullHttpRequest; import io.netty.handler.codec.http.HttpResponseStatus; import io.netty.handler.codec.http.HttpVersion; import io.netty.handler.codec.http.websocketx.*; import io.netty.util.CharsetUtil; import java.util.Date; /** * @author Lilinshen * @Title Core business processing class for processing/receiving/responding to WebSocket requests from clients * @Description Please fill in the related description * @Date 2018/5/23 10:36 */ public class MyWebSocketHandler extends SimpleChannelInboundHandler<Object> { private WebSocketServerHandshaker handshaker; private static final String WEB_SOCKET_URL = "ws://localhost:8888/websocket" ; /** * Call @param CTX * @throws Exception */ @Override public void channelActive(ChannelHandlerContext) ctx) throws Exception { NettyConfig.channelGroup.add(ctx.channel()); System.out.println(" Client/server connection enabled...") ); } /** * Call @param CTX * @throws Exception */ @override public void channelInactive(ChannelHandlerContext ctx) throws Exception { NettyConfig.channelGroup.remove(ctx.channel()); System.out.println(" Client and server connection closed...") ); } /** * Call @param CTX * @throws Exception */ @override public void channelReadComplete(ChannelHandlerContext ctx) throws Exception { ctx.flush(); } /** * Call @param CTX * @param Cause * @throws Exception */ @override public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception { cause.printStackTrace(); ctx.close(); } /** * Core methods for the server to handle webSocket requests ** @param channelHandlerContext * @param o * @throws Exception */ @Override protected void messageReceived(ChannelHandlerContext channelHandlerContext, Object o) throws Exception {if (o instanceof FullHttpRequest) {// Processes the HTTP handshake request sent by the client to the server handHttpRequest(channelHandlerContext, (FullHttpRequest) o); } else if (o instanceof WebSocketFrame) {// Handle webSocket connection business handWebsocketFrame(channelHandlerContext, (WebSocketFrame) o); }} /** * Handle the HTTP handshake request from the client to the server ** @param CTX * @param Request */ private void handHttpRequest(ChannelHandlerContext) ctx, FullHttpRequest request) { if (! request.getDecoderResult().isSuccess() || ! ( "websocket" ).equals(request.headers().get( "Upgrade" ))) { sendHttpResponse(ctx, request, new DefaultFullHttpResponse(HttpVersion.HTTP_1_1, HttpResponseStatus.BAD_REQUEST)); return; } WebSocketServerHandshakerFactory wsFactory = new WebSocketServerHandshakerFactory(WEB_SOCKET_URL, null, false); handshaker = wsFactory.newHandshaker(request); if (null == handshaker) { WebSocketServerHandshakerFactory.sendUnsupportedWebSocketVersionResponse(ctx.channel()); } else { handshaker.handshake(ctx.channel(), request); }} /** * The server responds to the client ** @param CTX * @param request * @param Response */ private void sendHttpResponse(ChannelHandlerContext ctx, FullHttpRequest request, DefaultFullHttpResponse response) { if (response.getStatus().code() ! = 200) { ByteBuf buf = Unpooled.copiedBuffer(response.getStatus().toString(), CharsetUtil.UTF_8); response.content().writeBytes(buf); buf.release(); } // Server sends data to client ChannelFuture ChannelFuture = ctx.channel().writeAndFlush(response); if (response.getStatus().code() ! = 200) { channelFuture.addListener(ChannelFutureListener.CLOSE); }} /** * Process WebSocket services between the client and server ** @param CTX * @param frame */ private void handWebsocketFrame(ChannelHandlerContext ctx, WebSocketFrame frame) {if (frame instanceof CloseWebSocketFrame) { handshaker.close(ctx.channel(), ((CloseWebSocketFrame) frame).retain()); If (frame instanceof PingWebSocketFrame) {ctx.channel().write(new) PongWebSocketFrame(frame.content().retain())); return; } // If the message is binary, throw an exception if (! (Frame Instanceof TextWebSocketFrame)) {system.out.println (" We do not currently support binary messages...") ); Throw new RuntimeException(" [" + this.getClass().getName() + ") does not support messages...") ); String Request = ((TextWebSocketFrame) frame).text(); String Request = ((TextWebSocketFrame) frame).text(); System.out.println( "===>>>" + request); TextWebSocketFrame tws = new TextWebSocketFrame(new Date().toString() + ctx.channel().id() + "===>>>" + request); / / mass, the service side of each connected to the client message NettyConfig. The channelGroup. WriteAndFlush (TWS); }}Copy the code
3. Initialize the components during the connection
package com.websocket.netty; import io.netty.channel.ChannelInitializer; import io.netty.channel.socket.SocketChannel; import io.netty.handler.codec.http.HttpObjectAggregator; import io.netty.handler.codec.http.HttpServerCodec; import io.netty.handler.stream.ChunkedWriteHandler; /** * @author lilinshen * @title * @description please fill in the description * @date 2018/5/23 11:12 */ public class MyWebSocketChannelHander extends ChannelInitializer<SocketChannel> { @Override protected void initChannel(SocketChannel socketChannel) throws Exception { socketChannel.pipeline().addLast( "http-codec" , new HttpServerCodec()); socketChannel.pipeline().addLast( "aggregator" , new HttpObjectAggregator(65536)); socketChannel.pipeline().addLast( "http-chunked" , new ChunkedWriteHandler()); socketChannel.pipeline().addLast( "handler" , new MyWebSocketHandler()); }}Copy the code
4. The entry of the program, responsible for starting the application
package com.websocket.netty; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.EventLoopGroup; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; /** * @author lilinshen * @title * @date 2018/5/23 11:17 */ public class Main {public static void Main (String[] args) { EventLoopGroup bossGroup = new NioEventLoopGroup(); EventLoopGroup workGroup = new NioEventLoopGroup(); try { ServerBootstrap bootstrap = new ServerBootstrap(); bootstrap.group(bossGroup, workGroup); bootstrap.channel(NioServerSocketChannel.class); bootstrap.childHandler(new MyWebSocketChannelHander()); System.out.println(" server enabled waiting for client to connect...") ); Channel channel = bootstrap.bind(8888).sync().channel(); channel.closeFuture().sync(); } catch (Exception e) { e.printStackTrace(); } the finally {/ / graceful exit bossGroup shutdownGracefully (); workGroup.shutdownGracefully(); }}}Copy the code
5. Websocket. HTML client code.
<html> <head> <meta http-equiv= "Content-Type" content= "text/html; </title> <script type= "text/javascript" > var socket; if (! window.WebSocket) { window.WebSocket = window.MozWebSocket; } if (window.WebSocket) { socket = new WebSocket( "ws://localhost:8888/websocket" ); socket.onmessage = function (ev) { var ta = document.getElementById( "responseContent" ); ta.value += ev.data + " \r\n " ; } socket.onopen = function (ev) { var ta = document.getElementById( "responseContent" ); Ta. Value += "Your current browser supports Websocket, please follow up \r\n"; } socket.onclose = function (ev) { var ta = document.getElementById( "responseContent" ); ta.value = "" ; Ta. Value = "webSocket connection closed \r\n"; }} else {alert(" Your browser does not support WebSocket "); } function send(message) { if (! window.WebSocket) { return; } if (socket.readyState == WebSocket.OPEN) { socket.send(message); } else {alert(" WebSocket connection failed to establish "); } } </script> </head> <body> <form onsubmit= " return false; " > <input type= "text" name= "message" value= "" /> <br/><br/> <input onclick= " send(this.form.message.value) " type= "Button" value= "send webSocket request" /> <hr color= "red" /> <h2> <textarea id= "responseContent" style= " width:1024px; height:300px; " ></textarea> </form> </body> </html>Copy the code
6. Start.
The main. Java class is the entry point to the program and is responsible for starting the application. 2. Open websocket. HTML in a browser to establish a WebSocket connection.