Netty makes it easy to communicate between Java programs using Netty’s client and server. But what if the client is a browser (Java programs don’t typically develop Web applications), and the client is a JavaScript program that uses the WebScoket protocol to communicate with each other?

The WebSocket protocol

concept

Familiar with Java network programming should understand Socket programming, which is used for communication between Java programs (Socket programming is also called Socket programming, it is in THE TCP/IP protocol between the transmission layer and an abstract layer between the application layer, to provide interface convenient application layer call to achieve communication between the network. Socket programming is divided into OIO and NIO, Netty is a communication framework encapsulated on the basis of NIO).

The WebSocket protocol is used for communication in Web applications (like sockets are also two-way communication). The Web already has HTTP, so why WebSocket? One drawback of HTTP is that the communication can only be initiated by the client, and the server cannot initiate the communication to the client. This results in clients getting server changes or notifications only through polling or holding HTTP connections, which is very wasteful. WebSocket was created to solve this problem.

Wikipedia:

WebSocket is a network transport protocol that enables full-duplex communication over a single TCP connection and is located at the application layer of the OSI model. WebSocket 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 browser and server only need to complete a handshake to create a persistent connection and two-way data transfer between the two.

The characteristics of

Its characteristics mainly have the following points.

  1. Based on THE TCP protocol, the server can take the initiative to push information to the client, and the client can also take the initiative to send information to the server, which is a real two-way communication.
  2. It has good compatibility with HTTP protocol. The default ports are also 80 and 443, and the handshake phase uses HTTP protocol, so it is not easy to mask the handshake and can pass various HTTP proxy servers.
  3. The data format is relatively light, with low performance overhead and high communication efficiency. You can send text or binary data.
  4. There are no same-origin restrictions, and clients can communicate with any server.
  5. The protocol identifier is WS (or WSS if SSL/TLS encryption is used) and the server URL is the URL.

Write WebSocket server based on Netty

Because the WebSocket protocol is used for Web application communication, it naturally supports writing servers in Node. So there are a lot of Node-based WebSocket servers out there. Java programming Websocket server is generally in Socket programming to encapsulate a layer, here of course, the recommended use of Netty to build. After all, Netty is a high-performance communication framework. It is also packaged on the basis of NIO, which makes operation easier.

Server main program

The main program is simple, just like a normal Netty server. The Webscoket wrapper is primarily in the processor.

public class WsServer {

    public static void main(String[] args) {
        // One main thread group (for listening for new connections and initializing channels), one distribution thread group (for IO event processing)
        EventLoopGroup mainGroup = new NioEventLoopGroup(1);
        EventLoopGroup subGroup = new NioEventLoopGroup();
        ServerBootstrap sb = new ServerBootstrap();
        try {
            sb.group(mainGroup, subGroup)
                    .channel(NioServerSocketChannel.class)
                    // Here is a custom channel initializer to add codecs and handlers
                    .childHandler(new WsChannelInitializer());
            // Bind port 88, which is the Websocket server's port
            ChannelFuture future = sb.bind(88).sync();
            // Block until the server is shut down
            future.channel().closeFuture().sync();
        } catch (InterruptedException e) {
            e.printStackTrace();
        } finally {
            // Release resourcesmainGroup.shutdownGracefully(); subGroup.shutdownGracefully(); }}}Copy the code

Channel initializer

Since the Websocket protocol is based on HTTP (the handshake phase uses HTTP), you need to add an HTTP codec as well as a message handler. Add a Webscoket handler to handle Webscoket handshakes and data transfers, and finally add a custom handler to handle IO events and interact with clients.

public class WsChannelInitializer extends ChannelInitializer {

    @Override
    protected void initChannel(Channel ch) {
        ChannelPipeline pipeline = ch.pipeline();
        // WebSocket is HTTP based, so use HTTP codec
        pipeline.addLast(new HttpServerCodec())
                // Support for writing big data streams
                .addLast(new ChunkedWriteHandler())
                // Aggregation of HTTP messages into FullHttpRequest or FullHttpResponse
                // This handler is almost always used in Netty programming
                .addLast(new HttpObjectAggregator(1024 * 64));
        // The above three processors support the HTTP protocol

        // The protocol handled by the webSocket server and used to specify the routing of client connections (in this case, /ws)
        Ws :// IP :port/ws
        // This handler does all the heavy lifting for running the WebSocket server
        // It handles the webSocket handshake and handles the control frame
        // Websocket transmits data in frames
        pipeline.addLast(new WebSocketServerProtocolHandler("/ws"));
        // Custom processor
        pipeline.addLast(newWsServerHandler()); }}Copy the code

Custom processor

The handler records and manages all client channels, receives messages from the client, and processes the corresponding IO events (bind the channel that the client user uniquely identifies and corresponds to the client when initializing the connection, and then push messages oriented).

// TextWebSocketFrame: In Netty, an object that is specifically used by webSockets to process text messages. Frame is the message carrier
public class WsServerHandler extends SimpleChannelInboundHandler<TextWebSocketFrame> {

    /** * is used to record and manage all client channels */
    private ChannelGroup clients = new DefaultChannelGroup(GlobalEventExecutor.INSTANCE);

    @Override
    protected void channelRead0(ChannelHandlerContext ctx, TextWebSocketFrame msg) throws Exception {
        // Get the text message from the client
        String text = msg.text();
        // This is a custom logging tool class, visible to other articles
        LogUtil.info("Received text message: [{}]", text);
        // This is where you can determine the type of message (such as initiating the connection, message transfer between clients, etc.)
        // Then you can Map the client Channel with the corresponding unique identifier to do directed push instead of broadcast

        // write back to client, this is broadcast
        clients.writeAndFlush(new TextWebSocketFrame("Server receives message:" + text));
    }

    /** * When the client connects to the server (open the connection) * get the client channel and put it into the ChannelGroup for management *@param ctx ChannelHandlerContext
     */
    @Override
    public void handlerAdded(ChannelHandlerContext ctx) {
        // Cannot be associated here because it cannot accept messages from the client and cannot be bound
        clients.add(ctx.channel());
    }

    /** * When the current method is triggered, the ChannelGroup automatically removes the corresponding client channel *@param ctx ChannelHandlerContext
     */
    @Override
    public void handlerRemoved(ChannelHandlerContext ctx) {
        LogUtil.info("Client disconnects, channel long ID: [{}]", ctx.channel().id().asLongText());
        LogUtil.info("Client disconnects, short ID of channel: [{}]", ctx.channel().id().asShortText()); }}Copy the code