netty 小demo
服務端
/**
* • 配置伺服器功能,如執行緒、埠 • 實現伺服器處理程式,它包含業務邏輯,決定當有一個請求連線或接收資料時該做什麼
*
* @author wilson
*
*/
public class EchoServer {
private final int port;
public EchoServer(int port) {
this.port = port;
}
public void start() throws Exception {
EventLoopGroup eventLoopGroup = null;
try {
//server端引導類
ServerBootstrap serverBootstrap = new ServerBootstrap();
//連線池處理資料
eventLoopGroup = new NioEventLoopGroup();
//裝配bootstrap
serverBootstrap.group(eventLoopGroup)
.channel(NioServerSocketChannel.class)//指定通道型別為NioServerSocketChannel,一種非同步模式,OIO阻塞模式為OioServerSocketChannel
.localAddress("localhost",port)//設定InetSocketAddress讓伺服器監聽某個埠已等待客戶端連線。
.childHandler(new ChannelInitializer<Channel>() {//設定childHandler執行所有的連線請求
@Override
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new EchoServerHandler());//註冊handler
}
});
// 最後繫結伺服器等待直到繫結完成,呼叫sync()方法會阻塞直到伺服器完成繫結,然後伺服器等待通道關閉,因為使用sync(),所以關閉操作也會被阻塞。
ChannelFuture channelFuture = serverBootstrap.bind().sync();
System.out.println("開始監聽,埠為:" + channelFuture.channel().localAddress());
channelFuture.channel().closeFuture().sync();
} finally {
eventLoopGroup.shutdownGracefully().sync();
}
}
public static void main(String[] args) throws Exception {
new EchoServer(20000).start();
}
}
public class EchoServerHandler extends ChannelInboundHandlerAdapter {
@Override
public void channelRead(ChannelHandlerContext ctx, Object msg)
throws Exception {
System.out.println("server 讀取資料……");
//讀取資料
ByteBuf buf = (ByteBuf) msg;
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req, "UTF-8");
System.out.println("接收客戶端資料:" + body);
//向客戶端寫資料
System.out.println("server向client傳送資料");
String currentTime = new Date(System.currentTimeMillis()).toString();
ByteBuf resp = Unpooled.copiedBuffer(currentTime.getBytes());
ctx.write(resp);
}
@Override
public void channelReadComplete(ChannelHandlerContext ctx) throws Exception {
System.out.println("server 讀取資料完畢..");
ctx.flush();//重新整理後才將資料發出到SocketChannel
}
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
cause.printStackTrace();
ctx.close();
}
}
客戶端
/**
* • 連線伺服器 • 寫資料到伺服器 • 等待接受伺服器返回相同的資料 • 關閉連線
*
* @author wilson
*
*/
public class EchoClient {
private final String host;
private final int port;
public EchoClient(String host, int port) {
this.host = host;
this.port = port;
}
public void start() throws Exception {
EventLoopGroup nioEventLoopGroup = null;
try {
// 客戶端引導類
Bootstrap bootstrap = new Bootstrap();
// EventLoopGroup可以理解為是一個執行緒池,這個執行緒池用來處理連線、接受資料、傳送資料
nioEventLoopGroup = new NioEventLoopGroup();
bootstrap.group(nioEventLoopGroup)//多執行緒處理
.channel(NioSocketChannel.class)//指定通道型別為NioServerSocketChannel,一種非同步模式,OIO阻塞模式為OioServerSocketChannel
.remoteAddress(new InetSocketAddress(host, port))//地址
.handler(new ChannelInitializer<SocketChannel>() {//業務處理類
@Override
protected void initChannel(SocketChannel ch)
throws Exception {
ch.pipeline().addLast(new EchoClientHandler());//註冊handler
}
});
// 連結伺服器
ChannelFuture channelFuture = bootstrap.connect().sync();
channelFuture.channel().closeFuture().sync();
} finally {
nioEventLoopGroup.shutdownGracefully().sync();
}
}
public static void main(String[] args) throws Exception {
new EchoClient("localhost", 20000).start();
}
}
public class EchoClientHandler extends SimpleChannelInboundHandler<ByteBuf> {
// 客戶端連線伺服器後被呼叫
@Override
public void channelActive(ChannelHandlerContext ctx) throws Exception {
System.out.println("客戶端連線伺服器,開始傳送資料……");
byte[] req = "QUERY TIME ORDER".getBytes();//訊息
ByteBuf firstMessage = Unpooled.buffer(req.length);//傳送類
firstMessage.writeBytes(req);//傳送
ctx.writeAndFlush(firstMessage);//flush
}
// • 從伺服器接收到資料後呼叫
@Override
protected void channelRead0(ChannelHandlerContext ctx, ByteBuf msg)
throws Exception {
System.out.println("client 讀取server資料..");
// 服務端返回訊息後
ByteBuf buf = (ByteBuf) msg;
byte[] req = new byte[buf.readableBytes()];
buf.readBytes(req);
String body = new String(req, "UTF-8");
System.out.println("服務端資料為 :" + body);
}
// • 發生異常時被呼叫
@Override
public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause)
throws Exception {
System.out.println("client exceptionCaught..");
// 釋放資源
ctx.close();
}
}