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