天天看点

Netty 学习(8)Netty Example Telnet

TelnetClient.java

package org.jboss.netty.example.telnet;

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStreamReader;
import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;

/**
 * Simplistic telnet client.
 */
public class TelnetClient {

    private final String host;
    private final int port;

    public TelnetClient(String host, int port) {
        this.host = host;
        this.port = port;
    }

    public void run() throws IOException {
        // Configure the client.
        ClientBootstrap bootstrap = new ClientBootstrap(
                new NioClientSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool()));

        // Configure the pipeline factory.
        bootstrap.setPipelineFactory(new TelnetClientPipelineFactory());

        // Start the connection attempt.
        ChannelFuture future = bootstrap.connect(new InetSocketAddress(host, port));

        // Wait until the connection attempt succeeds or fails.
        Channel channel = future.awaitUninterruptibly().getChannel();
        if (!future.isSuccess()) {
            future.getCause().printStackTrace();
            bootstrap.releaseExternalResources();
            return;
        }

        // Read commands from the stdin.
        ChannelFuture lastWriteFuture = null;
        BufferedReader in = new BufferedReader(new InputStreamReader(System.in));
        for (;;) {
            String line = in.readLine();
            if (line == null) {
                break;
            }

            // Sends the received line to the server.
            lastWriteFuture = channel.write(line + "\r\n");

            // If user typed the 'bye' command, wait until the server closes
            // the connection.
            if ("bye".equals(line.toLowerCase())) {
                channel.getCloseFuture().awaitUninterruptibly();
                break;
            }
        }

        // Wait until all messages are flushed before closing the channel.
        if (lastWriteFuture != null) {
            lastWriteFuture.awaitUninterruptibly();
        }

        // Close the connection.  Make sure the close operation ends because
        // all I/O operations are asynchronous in Netty.
        channel.close().awaitUninterruptibly();

        // Shut down all thread pools to exit.
        bootstrap.releaseExternalResources();
    }

    public static void main(String[] args) throws Exception {
        // Print usage if no argument is specified.
//        if (args.length != 2) {
//            System.err.println(
//                    "Usage: " + TelnetClient.class.getSimpleName() +
//                    " <host> <port>");
//            return;
//        }
//
//        // Parse options.
//        String host = args[0];
//        int port = Integer.parseInt(args[1]);

        String host = "127.0.0.1";
        int port = 3333;
        
        new TelnetClient(host, port).run();
    }
}
           

TelnetClientPipelineFactory.java

package org.jboss.netty.example.telnet;

import static org.jboss.netty.channel.Channels.*;

import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
import org.jboss.netty.handler.codec.frame.Delimiters;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;

/**
 * Creates a newly configured {@link ChannelPipeline} for a new channel.
 */
public class TelnetClientPipelineFactory implements
        ChannelPipelineFactory {

    public ChannelPipeline getPipeline() throws Exception {
        // Create a default pipeline implementation.
        ChannelPipeline pipeline = pipeline();

        // Add the text line codec combination first,
        pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
                8192, Delimiters.lineDelimiter()));
        pipeline.addLast("decoder", new StringDecoder());
        pipeline.addLast("encoder", new StringEncoder());

        // and then business logic.
        pipeline.addLast("handler", new TelnetClientHandler());

        return pipeline;
    }
}
           

TelnetClientHandler.java

package org.jboss.netty.example.telnet;

import java.util.logging.Level;
import java.util.logging.Logger;

import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;

/**
 * Handles a client-side channel.
 */
public class TelnetClientHandler extends SimpleChannelUpstreamHandler {

    private static final Logger logger = Logger.getLogger(
            TelnetClientHandler.class.getName());

    @Override
    public void handleUpstream(
            ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
        if (e instanceof ChannelStateEvent) {
            logger.info(e.toString());
        }
        super.handleUpstream(ctx, e);
    }

    @Override
    public void messageReceived(
            ChannelHandlerContext ctx, MessageEvent e) {
        // Print out the line received from the server.
        System.err.println(e.getMessage());
    }

    @Override
    public void exceptionCaught(
            ChannelHandlerContext ctx, ExceptionEvent e) {
        logger.log(
                Level.WARNING,
                "Unexpected exception from downstream.",
                e.getCause());
        e.getChannel().close();
    }
}
           

TelnetServer.java

package org.jboss.netty.example.telnet;

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

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

/**
 * Simplistic telnet server.
 */
public class TelnetServer {

    private final int port;

    public TelnetServer(int port) {
        this.port = port;
    }

    public void run() {
        // Configure the server.
        ServerBootstrap bootstrap = new ServerBootstrap(
                new NioServerSocketChannelFactory(
                        Executors.newCachedThreadPool(),
                        Executors.newCachedThreadPool()));

        // Configure the pipeline factory.
        bootstrap.setPipelineFactory(new TelnetServerPipelineFactory());

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

    public static void main(String[] args) throws Exception {
//        int port;
//        if (args.length > 0) {
//            port = Integer.parseInt(args[0]);
//        } else {
//            port = 8080;
//        }
    	
    	int port = 3333;
        new TelnetServer(port).run();
    }
}
           

TelnetServerPipelineFactory.java

package org.jboss.netty.example.telnet;

import static org.jboss.netty.channel.Channels.*;

import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.handler.codec.frame.DelimiterBasedFrameDecoder;
import org.jboss.netty.handler.codec.frame.Delimiters;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;

/**
 * Creates a newly configured {@link ChannelPipeline} for a new channel.
 */
public class TelnetServerPipelineFactory implements
        ChannelPipelineFactory {

    public ChannelPipeline getPipeline() throws Exception {
        // Create a default pipeline implementation.
        ChannelPipeline pipeline = pipeline();

        // Add the text line codec combination first,
        pipeline.addLast("framer", new DelimiterBasedFrameDecoder(
                8192, Delimiters.lineDelimiter()));
        pipeline.addLast("decoder", new StringDecoder());
        pipeline.addLast("encoder", new StringEncoder());

        // and then business logic.
        pipeline.addLast("handler", new TelnetServerHandler());

        return pipeline;
    }
}
           

TelnetServerHandler.java

package org.jboss.netty.example.telnet;

import java.net.InetAddress;
import java.util.Date;
import java.util.logging.Level;
import java.util.logging.Logger;

import org.jboss.netty.channel.ChannelEvent;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelFutureListener;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelUpstreamHandler;

/**
 * Handles a server-side channel.
 */
public class TelnetServerHandler extends SimpleChannelUpstreamHandler {

    private static final Logger logger = Logger.getLogger(
            TelnetServerHandler.class.getName());

    @Override
    public void handleUpstream(
            ChannelHandlerContext ctx, ChannelEvent e) throws Exception {
        if (e instanceof ChannelStateEvent) {
            logger.info(e.toString());
        }
        super.handleUpstream(ctx, e);
    }

    @Override
    public void channelConnected(
            ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {
        // Send greeting for a new connection.
        e.getChannel().write(
                "Welcome to " + InetAddress.getLocalHost().getHostName() + "!\r\n");
        e.getChannel().write("It is " + new Date() + " now.\r\n");
    }

    @Override
    public void messageReceived(
            ChannelHandlerContext ctx, MessageEvent e) {

        // Cast to a String first.
        // We know it is a String because we put some codec in TelnetPipelineFactory.
        String request = (String) e.getMessage();

        // Generate and write a response.
        String response;
        boolean close = false;
        if (request.length() == 0) {
            response = "Please type something.\r\n";
        } else if ("bye".equals(request.toLowerCase())) {
            response = "Have a good day!\r\n";
            close = true;
        } else {
            response = "Did you say '" + request + "'?\r\n";
        }

        // We do not need to write a ChannelBuffer here.
        // We know the encoder inserted at TelnetPipelineFactory will do the conversion.
        ChannelFuture future = e.getChannel().write(response);

        // Close the connection after sending 'Have a good day!'
        // if the client has sent 'bye'.
        if (close) {
            future.addListener(ChannelFutureListener.CLOSE);
        }
    }

    @Override
    public void exceptionCaught(
            ChannelHandlerContext ctx, ExceptionEvent e) {
        logger.log(
                Level.WARNING,
                "Unexpected exception from downstream.",
                e.getCause());
        e.getChannel().close();
    }
}
           

运行结果:

client

2014-1-24 9:48:50 org.jboss.netty.example.telnet.TelnetClientHandler handleUpstream
信息: [id: 0x9854dc73] OPEN
2014-1-24 9:48:50 org.jboss.netty.example.telnet.TelnetClientHandler handleUpstream
信息: [id: 0x9854dc73, /127.0.0.1:51937 => /127.0.0.1:3333] BOUND: /127.0.0.1:51937
2014-1-24 9:48:50 org.jboss.netty.example.telnet.TelnetClientHandler handleUpstream
信息: [id: 0x9854dc73, /127.0.0.1:51937 => /127.0.0.1:3333] CONNECTED: /127.0.0.1:3333
Welcome to Lenovo-PC!
It is Fri Jan 24 09:48:50 CST 2014 now. 
nihao
Did you say '   nihao'?
hello
Did you say '  hello'?
bye
Have a good day!
2014-1-24 9:49:00 org.jboss.netty.example.telnet.TelnetClientHandler handleUpstream
信息: [id: 0x9854dc73, /127.0.0.1:51937 :> /127.0.0.1:3333] DISCONNECTED
2014-1-24 9:49:00 org.jboss.netty.example.telnet.TelnetClientHandler handleUpstream
信息: [id: 0x9854dc73, /127.0.0.1:51937 :> /127.0.0.1:3333] UNBOUND
2014-1-24 9:49:00 org.jboss.netty.example.telnet.TelnetClientHandler handleUpstream
信息: [id: 0x9854dc73, /127.0.0.1:51937 :> /127.0.0.1:3333] CLOSED
           

server

2014-1-24 9:48:50 org.jboss.netty.example.telnet.TelnetServerHandler handleUpstream
信息: [id: 0xea8732af, /127.0.0.1:51937 => /127.0.0.1:3333] OPEN
2014-1-24 9:48:50 org.jboss.netty.example.telnet.TelnetServerHandler handleUpstream
信息: [id: 0xea8732af, /127.0.0.1:51937 => /127.0.0.1:3333] BOUND: /127.0.0.1:3333
2014-1-24 9:48:50 org.jboss.netty.example.telnet.TelnetServerHandler handleUpstream
信息: [id: 0xea8732af, /127.0.0.1:51937 => /127.0.0.1:3333] CONNECTED: /127.0.0.1:51937
2014-1-24 9:49:00 org.jboss.netty.example.telnet.TelnetServerHandler handleUpstream
信息: [id: 0xea8732af, /127.0.0.1:51937 :> /127.0.0.1:3333] DISCONNECTED
2014-1-24 9:49:00 org.jboss.netty.example.telnet.TelnetServerHandler handleUpstream
信息: [id: 0xea8732af, /127.0.0.1:51937 :> /127.0.0.1:3333] UNBOUND
2014-1-24 9:49:00 org.jboss.netty.example.telnet.TelnetServerHandler handleUpstream
信息: [id: 0xea8732af, /127.0.0.1:51937 :> /127.0.0.1:3333] CLOSED