您的位置:首页 > Web前端 > React

netty初析

2016-06-30 11:09 337 查看
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();
}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  netty socket reactor