netty(0 相关知识介绍)

目录

 

netty简介

示例1 discard

实例2 


netty简介

Netty是由JBOSS提供的一个java开源框架。Netty提供异步的、事件驱动的网络应用程序框架和工具,
用以快速开发高性能、高可靠性的网络服务器和客户端程序。

也就是说,Netty 是一个基于NIO的客户、服务器端编程框架,使用Netty 可以确保你快速和简单的开发出一个网络应用,
例如实现了某种协议的客户、服务端应用。Netty相当于简化和流线化了网络应用的编程开发过程,例如:基于TCP和UDP的socket服务开发。

“快速”和“简单”并不用产生维护性或性能上的问题。
Netty 是一个吸收了多种协议(包括FTP、SMTP、HTTP等各种二进制文本协议)的实现经验,
并经过相当精心设计的项目。最终,Netty 成功的找到了一种方式,在保证易于开发的同时还保证了其应用的性能,稳定性和伸缩性。 

以上摘自百度百科

下载netty的jar包 下载地址 http://netty.io/downloads.html 

 下载 netty-4.1.27.Final  版本 

官网上面已经说明了,jdk的版本需要1.6 以上

下载后解压,内容如下

示例1 discard

基于TCP的丢弃服务

   一个丢弃服务被定义为基于连接的应用程序
   TCP。服务器侦听TCP端口9上的TCP连接
   建立连接任何收到的数据都会被丢弃。没有
   响应已发送。这一直持续到主叫用户终止
   连接。

基于UDP的丢弃服务

   另一个丢弃服务被定义为基于数据报的应用程序
   UDP。服务器在UDP端口9上侦听UDP数据报
   收到数据报后,它就被丢弃了。没有回复。

netty 官方给出了一个示例,告诉你世界上最简单的协议不是"hello world " ,而是DISCARD(抛弃服务),这个协议将会抛弃任何收到的协议而不响应

package com.shj.netty;

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服务端
 * @Description
 * @Author shj
 * @Date 17:57 2018/7/19
 * @Param 
 * @return 
 **/


public class NettyServer {

    private static final int PORT=888;


    public static void main(String[] args) {
/**
 NioEventLoopGroup 是用来处理I/O操作的多线程事件循环器,Netty 提供了许多不同的
 EventLoopGroup 的实现用来处理不同的传输。在这个例子中我们实现了一个服务端的应用,
 因此会有2个 NioEventLoopGroup 会被使用。第一个经常被叫做‘boss’,用来接收进来的连
 接。第二个经常被叫做‘worker’,用来处理已经被接收的连接,一旦‘boss’接收到连接,就会
 把连接信息注册到‘worker’上。如何知道多少个线程已经被使用,如何映射到已经创建的
 Channel上都需要依赖于 EventLoopGroup 的实现,并且可以通过构造函数来配置他们的关
 系
 */
        EventLoopGroup bossGroup=new NioEventLoopGroup();
        EventLoopGroup workerGroup=new NioEventLoopGroup();

        try {
         /**  ServerBootstrap 是一个启动 NIO 服务的辅助启动类。你可以在这个服务中直接使用
            Channel,但是这会是一个复杂的处理过程,在很多情况下你并不需要这样做
           */
            ServerBootstrap serverBootstrap = new ServerBootstrap();
            serverBootstrap.group(bossGroup,workerGroup)
            /**
             * 这里我们指定使用 NioServerSocketChannel 类来举例说明一个新的 Channel 如何接收进来
             的连接
             **/
            .channel(NioServerSocketChannel.class)
            /**
             * 这里的事件处理类经常会被用来处理一个最近的已经接收的 Channel。ChannelInitializer 是
             一个特殊的处理类,他的目的是帮助使用者配置一个新的 Channel。也许你想通过增加一些
             处理类比如NettyServerHandler 来配置一个新的 Channel 或者其对应的ChannelPipeline
             来实现你的网络程序。当你的程序变的复杂时,可能你会增加更多的处理类到 pipline 上,然
             后提取这些匿名类到最顶层的类上
             **/
            .childHandler(new ChannelInitializer<SocketChannel>() {

                @Override
                protected void initChannel(SocketChannel ch) throws Exception {
                    ch.pipeline().addLast(new NettyServerHandler());
                }
            })
                    /**
                     * 
                     *你可以设置这里指定的 Channel 实现的配置参数。我们正在写一个TCP/IP 的服务端,因此
                    我们被允许设置 socket 的参数选项比如tcpNoDelay 和 keepAlive
                     **/
            .option(ChannelOption.SO_BACKLOG,128)
                    /**
                     option() 是提供给NioServerSocketChannel 用来接
                     收进来的连接。childOption() 是提供给由父管道 ServerChannel 接收到的连接,在这个例子
                     中也是 NioServerSocketChannel。
                     **/
             .childOption(ChannelOption.SO_KEEPALIVE,true);

//            绑定端口,开始接受进来的连接
            ChannelFuture channelFuture =serverBootstrap.bind(PORT).sync();
//          等待服务器 socket关闭
            channelFuture.channel().closeFuture().sync();


        }catch (Exception e){
                e.printStackTrace();
        }finally {
           workerGroup.shutdownGracefully();
           bossGroup.shutdownGracefully();
        }


    }

    

}

此时启动程序,然后在控制台输入   telnet 127.0.0.1 888

 

如果出现弹出窗口,则说明此服务器启动成功

为了更好的测试效果,修改服务端处理数据的方式,将收到的信息打印出来

  @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {

        ByteBuf byteBuf= (ByteBuf) msg;
        try{
        while (byteBuf.isReadable()){
            System.out.print( (char) byteBuf.readByte());
            System.out.flush();

        }

        }finally{
            ReferenceCountUtil.release(msg);
        }



    }

然后就可以将客户端发送的信息在控制台打印出来

实例2 echo 服务器

基于TCP的回声服务

   一个echo服务被定义为TCP上基于连接的应用程序。
   服务器侦听TCP端口7上的TCP连接
   建立连接任何收到的数据都会被发回。这个
   继续,直到主叫用户终止连接。

基于UDP的回声服务

   另一个echo服务被定义为基于数据报的应用程序
   UDP。服务器在UDP端口7上侦听UDP数据报
   接收到数据报,来自它的数据在回答中被发回
   数据报。

和 Discard 的区别就在于修改对数据的处理方式


    @Override
    public void channelRead(ChannelHandlerContext ctx, Object msg) throws Exception {
/**
 * ChannelHandlerContext 对象提供了许多操作,使你能够触发各种各样的 I/O 事件和操
 作。这里我们调用了 write(Object) 方法来逐字地把接受到的消息写入。请注意不同于
 DISCARD 的例子我们并没有释放接受到的消息,这是因为当写入的时候 Netty 已经帮我
 们释放了。
 **/        ctx.write(msg);

       /** ctx.write(Object) 方法不会使消息写入到通道上,他被缓冲在了内部,你需要调用
        ctx.flush() 方法来把缓冲区中数据强行输出。或者你可以用更简洁的
        cxt.writeAndFlush(msg) 以达到同样的目的。*/
        ctx.flush();


    }

猜你喜欢

转载自blog.csdn.net/aa15237104245/article/details/81112642
今日推荐