用Netty建立服务端, 首先我们应该新建立一个新的类, 作为服务端, 在其中写一个run方法, 作为启动:
1 public void run(){
2 // 处理 Nio的Accept
3 EventLoopGroup boss = new NioEventLoopGroup();
4 // 处理 Nio的Read和Write事件
5 EventLoopGroup worker = new NioEventLoopGroup();
6 try {
7 // Netty中服务端启动类
8 ServerBootstrap bootstrap = new ServerBootstrap();
9 // 启动类配置启动类中加入两个线程组
10 bootstrap.group(boss, worker);
11 // 启动类配置Channel配置,Channel为异步TCP Socket连接
12 bootstrap.channel(NioServerSocketChannel.class);
13 // 启动类配置SO_BACKLOG 含义允许连接客户端数量为2000
14 bootstrap.option(ChannelOption.SO_BACKLOG, Socketbacklog);
15 // 启动类配置SO_REUSEADDR 含义地址复用, 允许重复使用本地地址和端口
16 bootstrap.option(ChannelOption.SO_REUSEADDR, true);
17 bootstrap.childHandlernew ChannelInitializer<SocketChannel>() {
18 @Override
19 public void initChannel(SocketChannel ch) throws Exception {
20 ch.pipeline().addLast(new ServerHandler()); //添加服务端的业务处理类
21 }
22 });
23 // 保存Channel异步操作的结果
24 ChannelFuture channelFuture = bootstrap.bind(PORT).sync(); // 绑定端口, 并启动
25
26 channelFuture.channel().closeFuture().sync(); // 关闭连接
27 } catch (Exception e) {
28 e.printStackTrace();
29 } finally { //优雅的关闭服务器
30 boss.shutdownGracefully();
31 worker.shutdownGracefully();
32 }
33 }
34 }
1. NioEventLoopGroup 是用来处理I/O操作的多线程事件循环器,Netty 提供了许多不同的 EventLoopGroup 的实现用来处理不同的传输。在这个例子中我们实现了一个服务端的应用,因此会有2个 NioEventLoopGroup 会被使用。第一个经常被叫做‘boss’,用来接收进来的连接。第二个经常被叫做‘worker’,用来处理已经被接收的连接,一旦‘boss’接收到连接,就会把连接信息注册到‘worker’上。如何知道多少个线程已经被使用,如何映射到已经创建的 Channel 上都需要依赖于 EventLoopGroup 的实现,并且可以通过构造函数来配置他们的关系。
2. ServerBootStrap是一个启动 NIO 服务的辅助启动类。你可以在这个服务中直接使用 Channel,但是这会是一个复杂的处理过程,在很多情况下你并不需要这样做。
在这个方法中, 第20行的位置我们添加了业务的处理类ServerHandler, 这个类是我们接下来需要写的, 它继承自ChannelInboundHandlerAdapter类, 通过重写其中的一些方法, 我们就可以进行我们想要的操作了:
1 public void channelActive(ChannelHandlerContext ctx) // 在channel被启用的时候触发 (在建立连接的时候)
2 public void channelRead(ChannelHandlerContext ctx, Object msg) // 在数据被接收的时候调用
3 public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) // 出现报错时调用
msg是服务端接收到的数据, 而我们可以通过ctx.channel()方法来获取传来该值的channel
这里只列出了部分ChannelInboundHandlerAdapter中的方法, 其他的大家可以去查一下(其实这些方法命名十分简单明了了), 如果我们想讲客户端传来的数值都直接输出, 我们可以这样:
1 @Override
2 public void channelRead(ChannelHandlerContext ctx, Object msg) {
3 ctx.write(msg);
4 ctx.flush();
5 }
如果我们想传值到服务端去, 我们可以先定义一个Channel = ctx.channel(), 早通过channel的writeAndFlush()方法将信息作为参数传到相应的客户端去