Netty作为一个高性能网络通信框架,可以自定义实现不同协议的服务端和客户端程序。这里以telnet
为例做一个服务端程序。
Telnet协议是TCP/IP协议族中的一员,是Internet远程登陆服务的标准协议和主要方式。 ----百度百科
在项目中添加netty
在maven
的pom.xml
中添加:
<dependency>
<groupId>io.netty</groupId>
<artifactId>netty-all</artifactId>
<version>4.0.36.Final</version>
</dependency>
这里使用的版本为4.0.36.Final
。
创建一个Telnet服务
主程序NettyTelnetServer.java
public class NettyTelnetServer {
// 指定端口号
private static final int PORT = 8888;
private ServerBootstrap serverBootstrap;
private EventLoopGroup bossGroup = new NioEventLoopGroup(1);
private EventLoopGroup workerGroup = new NioEventLoopGroup();
public void open() throws InterruptedException {
serverBootstrap = new ServerBootstrap();
// 指定socket的一些属性
serverBootstrap.option(ChannelOption.SO_BACKLOG, 1024);
serverBootstrap.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class) // 指定是一个NIO连接通道
.handler(new LoggingHandler(LogLevel.INFO))
.childHandler(new NettyTelnetInitializer());
// 绑定对应的端口号,并启动开始监听端口上的连接
Channel ch = serverBootstrap.bind(PORT).sync().channel();
// 等待关闭,同步端口
ch.closeFuture().sync();
}
public void close(){
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
NioEventLoopGroup
对应一个被封装好的NIO线程池,bossGroup
负责收集客户端连接,workerGroup
负责处理每个连接的IO读写。
ServerBootstrap
是Socket
服务端启动类。通过这个类的实例,用户可以创建对应的服务端程序。
初始化配置类NettyTelnetInitializer.java
public class NettyTelnetInitializer extends ChannelInitializer<SocketChannel> {
private static final StringDecoder DECODER = new StringDecoder();
private static final StringEncoder ENCODER = new StringEncoder();
@Override
protected void initChannel(SocketChannel channel) throws Exception {
ChannelPipeline pipeline = channel.pipeline();
// Add the text line codec combination first,
pipeline.addLast(new DelimiterBasedFrameDecoder(8192, Delimiters.lineDelimiter()));
// 添加编码和解码的类
pipeline.addLast(DECODER);
pipeline.addLast(ENCODER);
// 添加处理业务的类
pipeline.addLast(new NettyTelnetHandler());
}
}
业务处理类NettyTelnetHandler.java
public class NettyTelnetHandler extends SimpleChannelInboundHandler<String> {
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
// Send greeting for a new connection.
ctx.write("Welcome to " + InetAddress.getLocalHost().getHostName() + "!\r\n");
ctx.write("It is " + new Date() + " now.\r\n");
ctx.flush();
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) {
cause.printStackTrace();
ctx.close();
}
@Override
protected void channelRead0(ChannelHandlerContext ctx, String request) throws Exception {
String response;
boolean close = false;
if (request.isEmpty()) {
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";
}
ChannelFuture future = ctx.write(response);
ctx.flush();
if (close) {
future.addListener(ChannelFutureListener.CLOSE);
}
}
}
运行服务
运行服务
public class NettyTest {
@Test
public void test() {
NettyTelnetServer nettyTelnetServer = new NettyTelnetServer();
try {
nettyTelnetServer.open();
} catch (InterruptedException e) {
nettyTelnetServer.close();
}
}
}
使用命令行工具访问telnet
服务
➜ telnet 127.0.0.1 8888
Trying 127.0.0.1...
Connected to localhost.
Escape character is '^]'.
Welcome to whthomasdeMacBook-Pro.local!
It is Tue Apr 12 11:37:20 CST 2016 now.
hello
Did you say 'hello'?
yes
Did you say 'yes'?
telnet
Did you say 'telnet'?
bye
Have a good day!
Connection closed by foreign host.
利用netty构建的telnet
服务器建立成功。
网友评论