說明
編寫簡單應答服務器目的就是爲了更好地瞭解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功能
確定即可!