Skip to content

Instantly share code, notes, and snippets.

@danbev
Created September 2, 2012 12:30
Show Gist options
  • Save danbev/3598124 to your computer and use it in GitHub Desktop.
Save danbev/3598124 to your computer and use it in GitHub Desktop.
Netty 4 WebSocket enhancement

Netty 4 WebSocket

Netty has had WebSocket support for quite a while now and it is easy to get up an running quickly with the existing examples. The example provided with Netty, consists of a handler which takes care of the HTTP Upgrade handshake, and also manages the WebSocket protocol. If you need to service http requests, for example serving static files, in addition to WebSocket calls then this approach works great.

But if all you want to do is create a custom application protocol on top of WebSocket and only service WebSocket requests, then the above solution is a fair amount of code that you'll have to maintain yourself. So, we set out to try to simplify this and this post describes what we came up with.

Below is an example of implementing a handler that will receive a TextWebSocketFrame

    public class CustomTextFrameHandler extends ChannelInboundMessageHandlerAdapter<TextWebSocketFrame> {
    
        @Override
        public void messageReceived(ChannelHandlerContext ctx, TextWebSocketFrame frame) throws Exception {
            String request = frame.getText();
            ctx.channel().write(new TextWebSocketFrame(request.toUpperCase()));
        }
    
    }

The text content is retrieved by calling getText and can then be parsed as required by the application protocol. This might involve parsing the String as JSON or whatever the protocol in question dictates.

Now, lets take a look at what is needed to bootstrap Netty:

    public static void main(String[] args) throws Exception {
        final ServerBootstrap sb = new ServerBootstrap();
        try {
            sb.eventLoop(new NioEventLoop(), new NioEventLoop())
             .channel(new NioServerSocketChannel())
             .localAddress(new InetSocketAddress(8080))
             .childHandler(new ChannelInitializer<SocketChannel>() {
                @Override
                public void initChannel(final SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(
                        new HttpRequestDecoder(),
                        new HttpChunkAggregator(65536),
                        new HttpResponseEncoder(),
                        new WebSocketProtocolHandler("/websocket"), 
                        new CustomTextFrameHandler());
                }
            });

            final Channel ch = sb.bind().sync().channel();
            System.out.println("Web socket server started at port 8080");

            ch.closeFuture().sync();
        } finally {
            sb.shutdown();
        }
    }

As you can see the CustomTextFrameHandler from the previous code example is the last handler added, and right before it we have a new handler named WebSocketProtocolHandler.

This feature has also been back ported to Netty 3.x. The CustomTextFrameHandler class would then look something like this

private class CustomTextFrameHandler extends SimpleChannelHandler {
        
        @Override
        public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception {
            if (e.getMessage() instanceof TextWebSocketFrame) {
                TextWebSocketFrame frame = (TextWebSocketFrame) e.getMessage();
                String request = frame.getText();
            }
        }
        
    }
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment