简单的介绍一些服务端代码的编写顺序。
1.得到 ServerBootstrap的对象,用来监听客户端
ServerBootstrap serverBootstrap = new ServerBootstrap();
2.创建两个线程池
EventLoopGroup boss = new NioEventLoopGroup(); EventLoopGroup worker = new NioEventLoopGroup();
boss用来对端口的监听,worker对数据进行处理
3.设置工厂
serverBootstrap.group(boss, worker); serverBootstrap.channel(NioServerSocketChannel.class);
4.设置,可以理解为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()); } });
5.设置TCP参数
serverBootstrap.option(ChannelOption.SO_BACKLOG, 2048);// serverSocketchannel的设置,链接缓冲池的大小 serverBootstrap.childOption(ChannelOption.SO_KEEPALIVE, true);// socketchannel的设置,维持链接的活跃,清除死链接 serverBootstrap.childOption(ChannelOption.TCP_NODELAY, true);// socketchannel的设置,关闭延迟发送
6.绑定端口
ChannelFuture future = serverBootstrap.bind(new InetSocketAddress( 9090));
7.(等待)关闭客户端
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权威指南作者的博客
http://www.infoq.com/cn/articles/netty-server-create