你好,游客 登录 注册 搜索
背景:
阅读新闻

Netty基础教程之服务器端创建

[日期:2016-07-27] 来源:Linux社区  作者:xujian2014 [字体: ]

阅读目录

  • 一、服务器端开发时序图
  • 二、Netty服务器端开发步骤
  • 三、Netty服务器开发示例代码
  • 四、参考资料

一、服务器端开发时序图

  

  图片来源:Netty权威指南(第2版)

二、Netty服务器端开发步骤

  使用Netty进行服务器端开发主要有以下几个步骤:

  1、创建ServerBootstrap实例

ServerBootstrap b=new ServerBootstrap();

  ServerBootstrap是Netty服务器端的启动辅助类,提供了一系列的方法用于设置服务器端启动相关的参数。

  2、设置并绑定Reactor线程池

EventLoopGroup bossGruop=new NioEventLoopGroup();//用于服务器端接受客户端的连接
EventLoopGroup workGroup=new NioEventLoopGroup();//用于网络事件的处理

  Netty的线程池是EventLoopGroup,它实际上是EventLoop的数组,EventLoop职责是处理所有注册到本线程多路复用器Selector上的Channel,Selector的轮询操作是由绑定的EventLoop线程run方法驱动。

  3、设置并绑定服务器端Channel

b.group(bossGruop, workGroup).channel(NioServerSocketChannel.class)

  Netty对原生的NIO类库进行封装,作为NIO服务端,需要创建ServerSocketChannel,对应的实现是NioServerSocketChannel。

  4、链路建立的时候创建并初始化ChannelPipeline

b.group(bossGruop, workGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>()

  ChannelPipeline的本质是一个负责处理网络事件的职责链,负责管理和执行ChannelHandler。网络事件以事件流的形式在ChannelPipeline中流转,由ChannelPipeline根据Channel|Handler的执行策略调度ChannelHandler的执行。典型的网络事件有:

  • 链路注册
  • 链路激活
  • 链路断开
  • 接收到请求信息
  • 请求信息接收并处理完毕
  • 发送应答消息
  • 链路发生异常
  • 用户自定义事件

  5、添加并设置ChannelHandler

b.group(bossGruop, workGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>()
 {
   @Override
   protected void initChannel(SocketChannel arg0) throws Exception
   {
    arg0.pipeline().addLast(new HelloServerHandler());
                    
   }
 }).option(ChannelOption.SO_BACKLOG, 1024);

  ChannelHandler是Netty提供给用户定制和扩展的接口,例如消息编解码、心跳、安全认证、TSL/SSL认证

  6、绑定并启动监听窗口

ChannelFuture f=b.bind(port).sync();

  经过一系列初始化和检测工作后,会启动监听端口,并将ServerSocketChannel注册到Selector上监听客户端连接

  7、Selector轮询

  由Reactor线程NioEventLoop负责调度和执行Selector轮询操作,选择准备就绪的Channel集合

  8、当轮询到准备就绪的Channel之后,就由Reactor线程NioEventLoop执行ChannelPipeline的相应方法,最终调度并执行ChannelHandler

public class HelloServerHandler extends ChannelHandlerAdapter

三、Netty服务器开发示例代码

   需求:服务器端实现,每连接一个客户端,在服务器控制台打印客户端输入的字符。(注:本代码使用的netty是netty-all-5.0.0.Alpha1-sources.jar版本)

  服务器端代码如下:

import io.netty.bootstrap.ServerBootstrap;
import io.netty.channel.ChannelFuture;
import io.netty.channel.ChannelInitializer;
import io.netty.channel.ChannelOption;
import io.netty.channel.EventLoopGroup;
import io.netty.channel.nio.NioEventLoopGroup;
import io.netty.channel.socket.SocketChannel;
import io.netty.channel.socket.nio.NioServerSocketChannel;
//Netty服务器端
public class HelloServer
{
    private int port;
    
    public HelloServer(int port)
    {
        super();
        this.port = port;
    }
    private void bind() throws InterruptedException
    {
        EventLoopGroup bossGruop=new NioEventLoopGroup();//用于服务器端接受客户端的连接
        EventLoopGroup workGroup=new NioEventLoopGroup();//用于网络事件的处理
        try
        {
            ServerBootstrap b=new ServerBootstrap();
            b.group(bossGruop, workGroup).channel(NioServerSocketChannel.class).childHandler(new ChannelInitializer<SocketChannel>()
            {
                @Override
                protected void initChannel(SocketChannel arg0) throws Exception
                {
                    arg0.pipeline().addLast(new HelloServerHandler());
                    
                }
            }).option(ChannelOption.SO_BACKLOG, 1024);//指定此套接口排队的最大连接个数
            ChannelFuture f=b.bind(port).sync();
            f.channel().closeFuture().sync();
        }
        finally
        {
            bossGruop.shutdownGracefully();
            workGroup.shutdownGracefully();
        }
    }
    public static void main(String[] args) throws InterruptedException
    {
        new HelloServer(8080).bind();
    }
}
 
 
import io.netty.buffer.ByteBuf;
import io.netty.channel.ChannelHandlerAdapter;
import io.netty.channel.ChannelHandlerContext;

//自定义的ChannelHandler
public class HelloServerHandler extends ChannelHandlerAdapter
{
    @Override
    public void channelActive(ChannelHandlerContext ctx) throws Exception
    {
        System.out.println("客户端连上了...");
    }
    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception
    {
        ByteBuf buf=(ByteBuf) msg;
        byte[] req=new byte[buf.readableBytes()];
        buf.readBytes(req);
        System.out.println("服务器端接收的消息:"+new String(req));
    }
    @Override
    public void channelReadComplete(ChannelHandlerContext ctx) throws Exception
    {
        ctx.flush();
    }
    @Override
    public void exceptionCaught(ChannelHandlerContext ctx, Throwable cause) throws Exception
    {
        ctx.close();
    }
}

  客户端:使用telnet模拟客户端输入,

  

   按住“ctrl+]”,然后输入指令send a

  

四、参考资料

  1、Netty权威指南(李林峰)【Netty权威指南 PDF完整版带目录书签+源码 下载地址 http://www.linuxidc.com/Linux/2016-07/133575.htm

运用Spring注解实现Netty服务器端UDP应用程序  http://www.linuxidc.com/Linux/2013-09/89780.htm

Netty源码学习笔记 http://www.linuxidc.com/Linux/2013-09/89778.htm

Netty使用实例 http://www.linuxidc.com/Linux/2013-09/89779.htm

Java NIO框架--Netty4的简单示例  http://www.linuxidc.com/Linux/2015-01/111335.htm

Netty 的详细介绍请点这里
Netty 的下载地址请点这里

本文永久更新链接地址http://www.linuxidc.com/Linux/2016-07/133584.htm

linux
相关资讯       Netty  Netty服务器端创建 
本文评论   查看全部评论 (2)
表情: 表情 姓名: 字数

       

评论声明
  • 尊重网上道德,遵守中华人民共和国的各项有关法律法规
  • 承担一切因您的行为而直接或间接导致的民事或刑事法律责任
  • 本站管理人员有权保留或删除其管辖留言中的任意内容
  • 本站有权在网站内转载或引用您的评论
  • 参与本评论即表明您已经阅读并接受上述条款
第 2 楼
* 于德晓会员 发表于 2016/8/8 15:07:45
为什么评论完毕后,没有显示在网页上?我找到原因了,因为之前导入4.0版本的包,maven 仓库管理的,修改pom文件后,发现这个配置是可以的,正确的。三克油!
第 1 楼
* 于德晓会员 发表于 2016/8/8 13:59:12
hello,我下载了jar吧,但是HelloServerHandler 中重写的方法channelActive有问题,