说明
编写简单应答服务器目的就是为了更好地了解netty工作机制,从而更熟练的灵活运用,仅此而已。
代码
DiscardServer.java
package com.moreday.netty.discard;
import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
/**
*
* @author 寻找手艺人
*
*/
public class DiscardServer {
private int port;
public DiscardServer(int port) {
super();
this.port = port;
}
public void run() throws Exception {
//用来接收进来的连接
EventLoopGroup bossGroup = new NioEventLoopGroup();
//用来处理已经被接收的连接,一旦‘boss’接收到连接,就会把连接信息注册到‘worker’上
EventLoopGroup workerGroup = new NioEventLoopGroup();
try {
//一个启动 NIO 服务的辅助启动类
ServerBootstrap b = new ServerBootstrap();
b.group(bossGroup, workerGroup)
.channel(NioServerSocketChannel.class)
.childHandler(new ChannelInitializer<SocketChannel>() {
@Override
protected void initChannel(SocketChannel ch) throws Exception {
// TODO Auto-generated method stub
ch.pipeline().addLast(new DiscardServerHandler());
}
})
.option(ChannelOption.SO_BACKLOG, 1024)
.childOption(ChannelOption.SO_KEEPALIVE,true);
//绑定端口,开始接收进来的链接
ChannelFuture f = b.bind(port).sync();
// 等待服务器 socket 关闭 。
// 在这个例子中,这不会发生,但你可以优雅地关闭你的服务器。
f.channel().closeFuture().sync();
} finally {
// TODO: handle finally clause
bossGroup.shutdownGracefully();
workerGroup.shutdownGracefully();
}
}
public static void main(String[] args) throws Exception {
int port =8080;
if(args.length>0) {
port = Integer.valueOf(args[0]);
new DiscardServer(port).run();
}
}
}
DiscardServerHandler.java
package com.moreday.netty.discard;
import io.netty.channel.ChannelHandlerContext;
import io.netty.channel.ChannelInboundHandlerAdapter;
/**
* 处理服务端 channel
*
* @author 寻找手艺人
*
*/
public class DiscardServerHandler extends ChannelInboundHandlerAdapter {
/**
* 每当从客户端收到新的数据时,这个方法会在收到消息时被调用,这个例子中,收到的消息的类型是 ByteBuf
*/
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
//ctx.write(Object) 方法不会使消息写入到通道上,他被缓冲在了内部,你需要调用 ctx.flush() 方法来把缓冲区中数据强行输出。或者你可以用更简洁的 cxt.writeAndFlush(msg) 以达到同样的目的。
//ctx.write(msg);
//ctx.flush();
try {
// 默默地丢弃收到的数据,ByteBuf 是一个引用计数对象,这个对象必须显示地调用 release() 方法来释放。
ByteBuf in = (ByteBuf) msg;
while(in.isReadable()) {
System.out.print((char) in.readByte());
System.out.flush();
}
} finally {
ReferenceCountUtil.release(msg);
}
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception {
// TODO Auto-generated method stub
// 当出现异常就关闭连接
cause.printStackTrace();
ctx.close();
}
}
调试
telnet为客户端连接
win+r开启win命令窗口
输入telnet ip port 回车
进入telnet客户端
在客户端输入,服务端后台打印出接收的内容信息,如下图所示
windows系统如何开启telnet
win+r 输入control指令回车
程序和功能
启动或关闭Windows功能
确定即可!