netty初析

Netty是由JBoss开发的一款用于快速构建高性能、高可靠性网络服务器和客户端的Java库。它提供了异步、事件驱动的网络应用框架及工具,简化了Socket编程。本文详细介绍了Netty的特点、优势,并通过实例演示了如何使用Netty搭建一个简单的服务端和客户端。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

Netty是什么?
本质:JBoss做的一个Jar包
目的:快速开发高性能、高可靠性的网络服务器和客户端程序
优点:提供异步的、事件驱动的网络应用程序框架和工具

通俗的说:一个好使的处理Socket的东东

如果没有Netty?
远古:java.net + java.io
近代:java.nio
其他:Mina,Grizzly

为什么不是Mina?
1、都是Trustin Lee的作品,Netty更晚;
2、Mina将内核和一些特性的联系过于紧密,使得用户在不需要这些特性的时候无法脱离,相比下性能会有所下降,Netty解决了这个设计问题;
3、Netty的文档更清晰,很多Mina的特性在Netty里都有;
4、Netty更新周期更短,新版本的发布比较快;
5、它们的架构差别不大,Mina靠apache生存,而Netty靠jboss,和jboss的结合度非常高,Netty有对google protocal buf的支持,有更完整的ioc容器支持(spring,guice,jbossmc和osgi);
6、Netty比Mina使用起来更简单,Netty里你可以自定义的处理upstream events 或/和 downstream events,可以使用decoder和encoder来解码和编码发送内容;
7、Netty和Mina在处理UDP时有一些不同,Netty将UDP无连接的特性暴露出来;而Mina对UDP进行了高级层次的抽象,可以把UDP当成”面向连接”的协议,而要Netty做到这一点比较困难。

Netty的特性
1. 设计
统一的API,适用于不同的协议(阻塞和非阻塞)
基于灵活、可扩展的事件驱动模型
高度可定制的线程模型
可靠的无连接数据Socket支持(UDP)
2. 性能
更好的吞吐量,低延迟
更省资源
尽量减少不必要的内存拷贝
3. 安全
完整的SSL/TLS和STARTTLS的支持
能在Applet与Android的限制环境运行良好
4. 健壮性
不再因过快、过慢或超负载连接导致OutOfMemoryError
不再有在高速网络环境下NIO读写频率不一致的问题
5. 易用
完善的JavaDoc,用户指南和样例
简洁简单
仅信赖于JDK1.5

Netty包的整体流程
NioServerSocketChannelFactory创建服务端的ServerSocketChannel,采用多线程执行非阻塞IO,和Mina的设计模式一样,都采用了Reactor模式。其中bossExecutor、workerExecutor是两个线程池,bossExecutor用来接收客户端连接,workerExecutor用来执行非阻塞的IO操作,主要是read,write。
这里写图片描述
这里写图片描述

下面举例一个简单的Netty服务实现

netty的模式其实就是reactor模式,如下表示reactor模式
这里写图片描述

服务端

package com.roger.java.pattrn.reactor;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ServerBootstrap;
import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioServerSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;

public class DiscardServer {

    public static void main(String[] args) throws Exception {  
        ChannelFactory factory = new NioServerSocketChannelFactory(  
            Executors.newCachedThreadPool(),  
            Executors.newCachedThreadPool());  
        ServerBootstrap bootstrap = new ServerBootstrap (factory);  
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {  
            public ChannelPipeline getPipeline() {  
                ChannelPipeline pipeline = Channels.pipeline();  
                pipeline.addLast("encode",new StringEncoder());  
                pipeline.addLast("decode",new StringDecoder());  
                pipeline.addLast("handler",new DiscardServerHandler());  
                //pipeline.addLast("handler",new DiscardServerHandler2());
                return pipeline;  
            }  
        });  
        bootstrap.setOption("child.tcpNoDelay", true);  
        bootstrap.setOption("child.keepAlive", true);  
        Channel bind = bootstrap.bind(new InetSocketAddress(8080));  
        System.out.println("Server已经启动,监听端口: " + bind.getLocalAddress() + ", 等待客户端注册。。。");  
    }  

}

Handler

package com.roger.java.pattrn.reactor;

import org.jboss.netty.channel.Channel;
import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;

public class DiscardServerHandler  extends SimpleChannelHandler {

    @Override  
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e)  throws Exception {  
         if (e.getMessage() instanceof String) {  
             String message = (String) e.getMessage();  
             System.out.println("Client发来:" + message);  
             e.getChannel().write("Server已收到刚发送的:" + message);  
             System.out.println("\n等待客户端输入。。。");  
         }  
         super.messageReceived(ctx, e);
    } 

    @Override  
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception {  
        System.out.println("有一个客户端注册上来了。。。");  
        System.out.println("Client:" + e.getChannel().getRemoteAddress());  
        System.out.println("Server:" + e.getChannel().getLocalAddress());  
        System.out.println("\n等待客户端输入。。。");  
        super.channelConnected(ctx, e);  
    }  

    @Override  
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {  
        e.getCause().printStackTrace();  
        Channel ch = e.getChannel();  
        ch.close();  
    }  

}

Client

package com.roger.java.pattrn.reactor;

import java.net.InetSocketAddress;
import java.util.concurrent.Executors;

import org.jboss.netty.bootstrap.ClientBootstrap;
import org.jboss.netty.channel.ChannelFactory;
import org.jboss.netty.channel.ChannelFuture;
import org.jboss.netty.channel.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;
import org.jboss.netty.handler.codec.string.StringDecoder;
import org.jboss.netty.handler.codec.string.StringEncoder;

public class TimeClient {

    public static void main(String[] args) throws Exception {  

        ChannelFactory factory = new NioClientSocketChannelFactory(  
        Executors.newCachedThreadPool(),  
        Executors.newCachedThreadPool());  
        ClientBootstrap bootstrap = new ClientBootstrap(factory);  
        bootstrap.setPipelineFactory(new ChannelPipelineFactory() {  
        public ChannelPipeline getPipeline() {  
                ChannelPipeline pipeline = Channels.pipeline();  
                pipeline.addLast("encode",new StringEncoder());  
                pipeline.addLast("decode",new StringDecoder());  
                pipeline.addLast("handler",new TimeClientHandler());
                return pipeline;  
            }  
        });  
        bootstrap.setOption("tcpNoDelay" , true);  
        bootstrap.setOption("keepAlive", true);  
        ChannelFuture future = bootstrap.connect(new InetSocketAddress("127.0.0.1", 8080));
        // Wait until the connection is closed or the connection attempt fails.  
        future.getChannel().getCloseFuture().awaitUninterruptibly();  
        // Shut down thread pools to exit.  
        bootstrap.releaseExternalResources();  
    }  

}

TimeClientHandler

package com.roger.java.pattrn.reactor;

import java.io.BufferedReader;
import java.io.InputStreamReader;

import org.jboss.netty.channel.ChannelHandlerContext;
import org.jboss.netty.channel.ChannelStateEvent;
import org.jboss.netty.channel.ExceptionEvent;
import org.jboss.netty.channel.MessageEvent;
import org.jboss.netty.channel.SimpleChannelHandler;

public class TimeClientHandler extends SimpleChannelHandler {

    private BufferedReader sin = new BufferedReader(new InputStreamReader(System.in));  

    @Override  
    public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e) throws Exception{ 
        System.out.println("已经与Server建立连接。。。。");  
        super.channelConnected(ctx, e);  
        System.out.println("\n请输入要发送的信息:"); 
        e.getChannel().write(sin.readLine());  
    }  

    @Override  
    public void messageReceived(ChannelHandlerContext ctx, MessageEvent e) throws Exception{  
        if (e.getMessage() instanceof String) {  
            String message = (String) e.getMessage();  
            System.out.println(message);  
            System.out.println("\n等待客户端输入。。。");  
            System.out.println("\n请输入要发送的信息:"); 
            e.getChannel().write(sin.readLine());  
        }
        super.messageReceived(ctx, e);   
    }  

    @Override  
    public void exceptionCaught(ChannelHandlerContext ctx, ExceptionEvent e) {  
        e.getCause().printStackTrace();  
        e.getChannel().close();  
    }   

}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值