前面文章講了如何通過Netty3寫一個簡單的例子,但是Netty4和Netty5同Netty3有很大的不同,這篇文章簡單介紹下如何通過Netty5寫一個簡單的服務端和客戶端例子。
服務端
1. 初始化一個NIO輔助服務類
//NIO服務的輔助啓動類
ServerBootstrap bootstrap = new ServerBootstrap();
2. 初始化兩個處理IO操作的多線程事件循環器,一個用於接收連接,一個用於處理客戶端i/o事件
//boss和worker
//EventLoopGroup是用來處理IO操作的多線程事件循環器
//負責接收客戶端連接線程
EventLoopGroup boss = new NioEventLoopGroup();
//負責處理客戶端i/o事件、task任務、監聽任務組
EventLoopGroup worker = new NioEventLoopGroup();
3. 設置服務端服務類的一些參數,包括channel綁定,事件循環器綁定等
//設置線程池
bootstrap.group(boss, worker);
//配置 Channel
bootstrap.channel(NioServerSocketChannel.class);
bootstrap.childHandler(new ChannelInitializer<Channel>() {
protected void initChannel(Channel ch) throws Exception {
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new StringEncoder());
ch.pipeline().addLast(new ServerHanler());
}
});
//BACKLOG用於構造服務端套接字ServerSocket對象,
// 標識當服務器請求處理線程全滿時,用於臨時存放已完成三次握手的請求的隊列的最大長度
bootstrap.option(ChannelOption.SO_BACKLOG, 2048);
//是否啓用心跳保活機制
bootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);
bootstrap.childOption(ChannelOption.TCP_NODELAY, true);
這裏註冊了一個自定義的事件處理的類ServerHanler,該類繼承於SimpleChannelInboundHandler<String>,ServerHanler主要處理代碼如下:
@Override
protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println(msg);
ctx.channel().writeAndFlush("hi");
ctx.writeAndFlush("hi");
}
4. 綁定端口,開始監聽連接,並阻塞主線程退出
ChannelFuture future = bootstrap.bind(10010);
System.out.println("start");
//服務器關閉監聽
/*channel.closeFuture().sync()實際是如何工作:
channel.closeFuture()不做任何操作,只是簡單的返回channel對象中的closeFuture對象,對於每個Channel對象,都會有唯一的一個CloseFuture,用來表示關閉的Future,
所有執行channel.closeFuture().sync()就是執行的CloseFuturn的sync方法,從上面的解釋可以知道,這步是會將當前線程阻塞在CloseFuture上*/
future.channel().closeFuture().sync();
客戶端
1. 初始化一個NIO輔助服務類
//服務類
Bootstrap bootstrap=new Bootstrap();
2. 初始化一個處理IO操作的多線程循環處理器
//worker
EventLoopGroup worker=new NioEventLoopGroup();
3. 設置NIO輔助類的一些屬性,包括指定多線程循環處理器、指定channel和指定初始化處理操作
//設置IO多線程循環處理器
bootstrap.group(worker);
//設置Channel
bootstrap.channel(NioSocketChannel.class);
//指定客戶端初始化處理操作
bootstrap.handler(new ChannelInitializer<Channel>() {
@Override
protected void initChannel(Channel ch) throws Exception{
ch.pipeline().addLast(new StringDecoder());
ch.pipeline().addLast(new StringEncoder());
ch.pipeline().addLast(new ClientHandler());
}
});
此處有一個處理消息的自定義類ClientHandler,繼承自SimpleChannelInboundHandler<String>,ClientHandler主要代碼如下:
@Override
protected void messageReceived(ChannelHandlerContext ctx, String msg) throws Exception {
System.out.println("客戶端收到消息:"+msg);
}
4. 開始連接服務端
ChannelFuture connect=bootstrap.connect("127.0.0.1",10010);
5.開始進行發送消息
BufferedReader bufferedReader=new BufferedReader(new InputStreamReader(System.in));
while (true){
System.out.println("請輸入:");
String msg= bufferedReader.readLine();
connect.channel().writeAndFlush(msg);
}