//
you're reading...
General, Netty HowTo

HOW TO: HTTP Server and Long Polling

In the current HOW TO,  I will show how easily a HTTP server can be written using a netty library and how this can be used to implement a long polling. I have simple http client using java libraries to test this. The code for this can be found at here.

HTTP Server

This is very simple with netty. Netty is a library that enables easy development of any network related code. To create and start a netty server you need to do this:

            Executor bossthrd = Executors.newCachedThreadPool();
            Executor workthrd = Executors.newCachedThreadPool();

            // Configure the server.
            ServerBootstrap bootstrap = new ServerBootstrap(
                    new NioServerSocketChannelFactory(
                            bossthrd, workthrd));

            // Set up the event pipeline factory.
            bootstrap.setPipelineFactory(getPipelineFactory());

            // Bind and start to accept incoming connections.
            bootstrap.bind(new InetSocketAddress(_communicationport));

What is important here is the pipeline factory. In netty, all messages passing through the socket goes via a pipeline of handlers. These handlers control how the arriving or sent data is formatted and hence what type of server is created. Data that arrives is handled by Upstream handlers and data sent is handled by downstream handlers. Netty provides a number of standard handlers that can be used to implement standard servers. In our case we want to implement a http server, so we can use the HttpRequestDecoder handler and the HttpResponseEncoder handler. Along with this, we want our custom request handler to handle the HTTP request messages. So our getPipeline looks like below:

        ChannelPipeline pipeline = pipeline();        pipeline.addLast("decoder", new HttpRequestDecoder());
        pipeline.addLast("encoder", new HttpResponseEncoder());
        pipeline.addLast("handler", new RequestHandler());
        return pipeline;

Our RequestHandler class extends the SimpleChannelUpstreamHandler and does what is specific to our server. This can simply write back a response as below in the messageReceived function.

            HttpResponse response = new DefaultHttpResponse(HTTP_1_1, OK);
            response.setContent(ChannelBuffers.copiedBuffer("Some response", CharsetUtil.UTF_8));
            response.setHeader(CONTENT_LENGTH, response.getContent().readableBytes());
            response.setHeader(CONTENT_TYPE, "text/html");
            ChannelFuture future = _externalEvent.getChannel().write(response);
            future.awaitUninterruptibly();//wait till this writes only then next can be written

But we will do something different so that we can implement Long polling.

Long Polling

Long polling is push technology, where the server does not respond immediately but responds when data is available. The client sends across a request and waits for the response and when the response is available it processes it. Once a response is received, the client re-initiates a request and waits for the next response. To implement this in a server using netty, it is required that the channel on which the request arrived is saved, so that the response can be sent on the same channel.

In our current sample, we will delay the processing by adding a sleep, but this can be delayed by any mechanism.  We will create an object called RequestDataScope (See the code) for every request which maintains the channel and content of the request. We will post it into a queue which is processed by a worker thread. This thread delays the response sent. The response sent is the same data as that which arrived on the channel.

So, RequestHandler class declares a queue:

    private Queue _queueRequests = new ConcurrentLinkedQueue();

This queue is processed by a single thread currently which does nothing more other than sleep and send a response as below:

        public void run()
        {
            while (true)
            {
                try
                {
                    if (!_queueRequests.isEmpty())
                    {
                        RequestDataScope process = _queueRequests.poll();
                        InputStream str = process.data().datastream();
                        StringBuffer buff = readStream(str);
                        process.transmit(buff.toString());
                    }
                    Thread.currentThread().sleep(10000); //long sleep here
                }
                catch (Exception e)
                {
                    e.printStackTrace();
                }
            }
        }

The transmit function called is a function in RequestDataScope and sends the http response as shown above in HTTP Server section. To post the requests that arrive into the queue we override the messageReceived function in RequestHandler as below:

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)
        throws Exception
    {
        RequestDataScope scope = new RequestDataScope(getHost(request, "unknown"), e);
        _queueRequests.add(scope);
    }

This creates a HTTP Server that implements Long Polling. To test this we will use a simple test java client that uses the java HttpURLConnection and sends and receives data using standard functions. Check out the HTTPTestClient code for implementation.

 

Advertisements

Discussion

2 thoughts on “HOW TO: HTTP Server and Long Polling

  1. The link to the HTTPTestClient code is not available.

    Posted by John | November 10, 2014, 9:41 pm

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: