The Netty project provides an asynchronous event-driven network application framework and tooling for the rapid development of maintainable high-performance high-scalability protocol servers and clients. In this tutorial we we will show how to use it to enhance the application server capabilities.

 

So, Netty is a NIO client server framework which enables quick and easy development of network applications such as protocol servers and clients. It greatly simplifies and streamlines network programming such as TCP and UDP socket server development.

 'Quick and easy' does not mean that a resulting application will suffer from a maintainability or a performance issue. Netty has been designed carefully with the experiences earned from the implementation of a lot of protocols such as FTP, SMTP, HTTP, and various binary and text-based legacy protocols. As a result, Netty has succeeded to find a way to achieve ease of development, performance, stability, and flexibility without a compromise.

In the product documentation you can find some basic and advanced examples of Netty Servers: our aim is to show how to run a basic Server example at Server startup. JBoss AS by itself does not provide a custom Startup class, however this can be easily achieved by deploying an EJB 3.1 compatible marked with @Startup


import javax.annotation.PostConstruct;
import javax.ejb.Singleton;
import javax.ejb.Startup;

import com.sample.NettyServer;

@Singleton(name="NettyEJB")
@Startup
public class NettyEJB {
@PostConstruct

        void init() {

         try {
                new NettyServer().startServer();
            } catch (Exception e) {
                // TODO Auto-generated catch block
                e.printStackTrace();
            }

        }
}

And here's a minimal Netty Echo server which listen for requests on port 8888:

package com.sample;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.*;
import org.jboss.netty.channel.*;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;

public class NettyServer {

    public void startServer() throws Exception {
        ChannelFactory factory =
            new NioServerSocketChannelFactory(
                    Executors.newCachedThreadPool(),
                    Executors.newCachedThreadPool());

        ServerBootstrap bootstrap = new ServerBootstrap(factory);

        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {
            public ChannelPipeline getPipeline() {
                return Channels.pipeline(new EchoServerHandler());
            }
        });

        bootstrap.setOption("child.tcpNoDelay", true);
        bootstrap.setOption("child.keepAlive", true);

        bootstrap.bind(new InetSocketAddress(8888));
        System.out.println("Server Started!");
    }
}

ChannelFactory is a factory which creates and manages Socket Channels and its related resources. It processes all I/O requests and performs I/O to generate ChannelEvents. Netty provides various ChannelFactory implementations: in this example, we are using NioServerSocketChannelFactory.

Next, the ServerBootstrap is a helper class that sets up a server. The bootstrap class as it is does not provide any special functionalities. In particular we need to define what happens when a new connection is received.  Let's  create a new ChannelPipeline will be created by the specified ChannelPipelineFactory. The new pipeline contains the EchoServerHandler. In more complex applications, it is likely that you will add more handlers to the pipeline and extract this anonymous class into a top level class eventually.

EchoServerHandler extends SimpleChannelHandler, which is an implementation of ChannelHandler. SimpleChannelHandler provides various event handler methods that you can override. For now, it is just enough to extend SimpleChannelHandler rather than to implement the handler interfaces by yourself.
We override the messageReceived event handler method here. This method is called with a MessageEvent, which contains the received data, whenever new data is received from a client.


package com.sample;

import org.jboss.netty.buffer.ChannelBuffer;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandler;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;

public class EchoServerHandler extends SimpleChannelHandler { 

    @Override
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) { 
         ChannelBuffer  buf = (ChannelBuffer) e.getMessage();
            while(buf.readable()) {
                System.out.println((char) buf.readByte());
                System.out.flush();
            }
    }

    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) { 
        e.getCause().printStackTrace();
        
        Channel ch = e.getChannel();
        ch.close();
    }
}


We are ready to go now. What's left is to bind to the port and to start the server. Here, we bind to the port 8888 of all NICs (network interface cards) in the machine. You can now call the bind method as many times as you want (with different bind addresses.)

Before deploying your EJB on the server, JBoss AS 7 users still miss one thing: the Netty libraries are not classified as automatic dependencies, therefore we need telling our application to trigger org.jboss.netty module. Just add to your MANIFEST.MF file the following:

 

 

Manifest-Version: 1.0
Dependencies: org.jboss.netty

 

You can connect with any client: the simplest one is telnet 8888

Or if you prefer use any Socket client, like this NIO client:


package com.sample;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;

public class NIOClient {

    SelectionKey selkey=null;
    Selector sckt_manager=null;
    public static void coreClient()
    {

        BufferedReader stdin=new BufferedReader(new InputStreamReader(System.in));
        SocketChannel sc = null;
        try
        { sc = SocketChannel.open();
        sc.configureBlocking(false);       
        sc.connect(new InetSocketAddress(8888));  
        while (!sc.finishConnect())
        {   
        } 

        System.out.println("Enter the text");
        String HELLO_REQUEST =stdin.readLine().toString();

        System.out.println("Sending a request to HelloServer");    
        ByteBuffer buffer = ByteBuffer.wrap(HELLO_REQUEST.getBytes());    
        sc.write(buffer); 


        } 
        catch (IOException e) 
        {          
            e.printStackTrace();    
        }
        finally
        {       
            if (sc != null)
            {            
                try 
                {             
                    sc.close();            
                }
                catch (Exception e)
                {           
                    e.printStackTrace();       
                }       
            } 
        }   }

    public static void main(String args[]) {
        coreClient();

    }
}

That's just a first taste of this awesome library, which allows advanced Server features like Asynchronous I/O API, TimeBased servers, an extensible event model, built-in security and much more!

For futher reading: http://docs.jboss.org/netty/3.2/guide/html/index.html

0
0
0
s2smodern