maven版本依賴
<dependency> <groupId>io.netty</groupId> <artifactId>netty-all</artifactId> <version>5.0.0.Alpha2</version> </dependency>
服務端代碼的編寫順序。
- 得到 ServerBootstrap的對象,用來監聽客戶端
ServerBootstrap serverBootstrap = new ServerBootstrap();
- 創建兩個線程池
EventLoopGroup boss = new NioEventLoopGroup(); EventLoopGroup worker = new NioEventLoopGroup();
boss用來對端口的監聽,worker對數據進行處理
- 設置工廠
serverBootstrap.group(boss, worker); serverBootstrap.channel(NioServerSocketChannel.class);
- 設置,可以理解為netty3中的管道
serverBootstrap.childHandler(new ChannelInitializer<Channel>() { @Override protected void initChannel(Channel channel) throws Exception { /** * 將“上傳下載”數據裝飾成String類型 */ channel.pipeline().addLast(new StringDecoder()); channel.pipeline().addLast(new StringEncoder()); // 要處理的Handler channel.pipeline().addLast(new ServerHandler2()); } });
- 設置TCP參數
serverBootstrap.option(ChannelOption.SO_BACKLOG, 2048);// serverSocketchannel的設置,鏈接緩沖池的大小 serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);// socketchannel的設置,維持鏈接的活躍,清除死鏈接 serverBootstrap.childOption(ChannelOption.TCP_NODELAY, true);// socketchannel的設置,關閉延遲發送
- 綁定端口
ChannelFuture future = serverBootstrap.bind(new InetSocketAddress(9090));
- (等待)關閉客戶端
Channel channel = future.channel(); channel.closeFuture().sync();
完整代碼如下:
服務端:package com.netty5.server; import java.net.InetSocketAddress; import io.netty.bootstrap.ServerBootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.ChannelOption; import io.netty.channel.EventLoopGroup; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioServerSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; /** * @author Chalmers 2016年2月20日 下午7:52:49 */ public class NettyServer2 { public static void main(String[] args) { // 得到ServerBootstrap對象 ServerBootstrap serverBootstrap = new ServerBootstrap(); // 創建線程池 EventLoopGroup boss = new NioEventLoopGroup(); EventLoopGroup worker = new NioEventLoopGroup(); try { // 類似於Netty3中的工廠 serverBootstrap.group(boss, worker); serverBootstrap.channel(NioServerSocketChannel.class); // 類似於Netty3中的管道 serverBootstrap.childHandler(new ChannelInitializer<Channel>() { @Override protected void initChannel(Channel channel) throws Exception { /** * 將“上傳下載”數據裝飾成String類型 */ channel.pipeline().addLast(new StringDecoder()); channel.pipeline().addLast(new StringEncoder()); // 要處理的Handler channel.pipeline().addLast(new ServerHandler2()); } }); // 設置參數,TCP參數 serverBootstrap.option(ChannelOption.SO_BACKLOG, 2048);// serverSocketchannel的設置,鏈接緩沖池的大小 serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);// socketchannel的設置,維持鏈接的活躍,清除死鏈接 serverBootstrap.childOption(ChannelOption.TCP_NODELAY, true);// socketchannel的設置,關閉延遲發送 // 綁定端口,並且返回ChannelFuture對象 ChannelFuture future = serverBootstrap.bind(new InetSocketAddress( 9090)); System.out.println("啟動服務器..."); // 等待客戶端的關閉 Channel channel = future.channel(); // 要記得是closeFuture(),作用是等待服務端的關閉 channel.closeFuture().sync(); // 該條語句不會輸出,原因:上面沒有關閉... // System.out.println("客戶端已經關閉..."); } catch (Exception e) { e.printStackTrace(); } finally { boss.shutdownGracefully(); worker.shutdownGracefully(); } } } class ServerHandler2 extends SimpleChannelInboundHandler<String> { @Override protected void messageReceived(ChannelHandlerContext arg0, String arg1) throws Exception { // 輸出接收到的數據 System.out.println(arg1); // 向客戶端發送數據 arg0.channel().writeAndFlush("hi"); } /** * */ @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { super.channelActive(ctx); System.out.println("channelActive"); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { super.channelInactive(ctx); System.out.println("channelInactive"); } }
客戶端:
package com.netty.client; import java.io.BufferedReader; import java.io.IOException; import java.io.InputStreamReader; import io.netty.bootstrap.Bootstrap; import io.netty.channel.Channel; import io.netty.channel.ChannelFuture; import io.netty.channel.ChannelHandlerContext; import io.netty.channel.ChannelInitializer; import io.netty.channel.EventLoopGroup; import io.netty.channel.SimpleChannelInboundHandler; import io.netty.channel.nio.NioEventLoopGroup; import io.netty.channel.socket.nio.NioSocketChannel; import io.netty.handler.codec.string.StringDecoder; import io.netty.handler.codec.string.StringEncoder; /** * @author Chalmers 2016年2月20日 下午8:31:25 */ public class Client { public static void main(String[] args) { Bootstrap bootstrap = new Bootstrap(); EventLoopGroup worker = new NioEventLoopGroup(); bootstrap.channel(NioSocketChannel.class); bootstrap.group(worker); bootstrap.handler(new ChannelInitializer<Channel>() { @Override protected void initChannel(Channel channel) throws Exception { channel.pipeline().addLast(new StringEncoder()); channel.pipeline().addLast(new StringDecoder()); channel.pipeline().addLast(new ClientHandler()); } }); ChannelFuture future = bootstrap.connect("127.0.0.1", 9090); BufferedReader br = new BufferedReader(new InputStreamReader(System.in)); while (true) { System.out.print("輸入: "); try { String line = br.readLine(); future.channel().writeAndFlush(line); } catch (IOException e) { e.printStackTrace(); } } } } class ClientHandler extends SimpleChannelInboundHandler<String> { @Override protected void messageReceived(ChannelHandlerContext arg0, String arg1) throws Exception { System.out.println("收到服務端發送的消息..." + arg1); } @Override public void channelActive(ChannelHandlerContext ctx) throws Exception { // TODO Auto-generated method stub super.channelActive(ctx); } @Override public void channelInactive(ChannelHandlerContext ctx) throws Exception { // TODO Auto-generated method stub super.channelInactive(ctx); } }
因為netty5與netty3的差別挺大,所以注意區分開。
http://moonmonster.iteye.com/blog/2278672
當然,因為本人水平有限,所以更詳細的解釋可見
netty權威指南作者的博客