`
weiwei5910
  • 浏览: 27614 次
  • 性别: Icon_minigender_1
  • 来自: 武汉
社区版块
存档分类

初学Java NIO框架Netty(一) 之 Hello

 
阅读更多

听朋友介绍这个框架于是学习之

首先非常感谢下面这两篇博文,很大部分代码和注释都参考了他们

http://deep-fish.iteye.com/blog/1819647

http://blog.163.com/linfenliang@126/blog/static/127857195201210744448686/?suggestedreading


没有废话了,直接代码加注释


HelloServer 服务端

package com.wei.study;

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

import org.jboss.netty.bootstrap.ServerBootstrap;
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;

/**
 * 
 * @author wangwei
 * Jun 7, 2013
 */
public class HelloServer {

	public static void main(String[] args) {
		/*
		 * 基于NIO的用于创建服务器端channel的channelFactory
		 * 这个类利用非阻塞I/O模式引入NIO,这样可以有效地向多个并发连接提供Channel 
		 * 
		 * 在实现类中传入了两个cached线程池
		 * 前面一个代表boss线程,后面一个代表worker线程
		 * 
		 * Boss线程: 
		 * 每个server服务器都会有一个boss线程,每绑定一个InetSocketAddress都会产生一个boss线程,比如:我们开启了两个服务器端口80和443,则我们会有两个boss线程。
		 * 一个boss线程在端口绑定后,会接收传进来的连接,一旦连接接收成功,boss线程会指派一个worker线程处理连接。 
		 *
		 * Worker线程: 
		 * 一个NioServerSocketChannelFactory会有一个或者多个worker线程。一个worker线程在非阻塞模式下为一个或多个Channels提供非阻塞 读或写 
		 * 
		 * 简单来说,Boss线程用来接收客户端请求;worker用来执行非阻塞的IO操作,主要是read,write。
		 */
		ChannelFactory tcpChannelFactory =  new NioServerSocketChannelFactory(Executors.newCachedThreadPool(),Executors.newCachedThreadPool());
		
		//server服务启动器
		ServerBootstrap bootstrap = new ServerBootstrap(tcpChannelFactory);
		
		//管道工厂 设置处理客户端消息和消息事件的Handler类
		bootstrap.setPipelineFactory(new ChannelPipelineFactory(){
			@Override
			public ChannelPipeline getPipeline() throws Exception {
				return Channels.pipeline(new HelloServerHandler());
			}
		});
		//开放监听8000端口代客户端通信
		bootstrap.bind(new InetSocketAddress(8000));
	}
}


HelloServerHandler服务处理类

package com.wei.study;

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

/**
 * 
 * @author wangwei
 * Jun 7, 2013
 */
public class HelloServerHandler extends SimpleChannelHandler {

	@Override
	//设置连接时触发事件
	public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
			throws Exception {
		System.out.println("Hello,I'm server.");
	}
	
	
}


HelloClient 客户端类

package com.wei.study;

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.ChannelPipeline;
import org.jboss.netty.channel.ChannelPipelineFactory;
import org.jboss.netty.channel.Channels;
import org.jboss.netty.channel.socket.nio.NioClientSocketChannelFactory;

/**
 * 
 * @author wangwei
 * Jun 7, 2013
 */
public class HelloClient {
	
	public static void main(String[] args) {
		//与服务端相同
		ChannelFactory clientSocketChannel = new NioClientSocketChannelFactory(Executors.newCachedThreadPool(),Executors.newCachedThreadPool());
		//与服务端相同
		ClientBootstrap bootstrap = new ClientBootstrap(clientSocketChannel);
		
		//与服务端相同
		bootstrap.setPipelineFactory(new ChannelPipelineFactory(){

			@Override
			public ChannelPipeline getPipeline() throws Exception {
				return Channels.pipeline(new HelloClientHandler());
			}
		});
		
		//连接到IP地址及端口
		bootstrap.connect(new InetSocketAddress("127.0.0.1",8000));
	}
	
}

HelloClient 客户端处理类

package com.wei.study;

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

/**
 * 
 * @author wangwei
 * Jun 7, 2013
 */
public class HelloClientHandler extends SimpleChannelHandler {
	
	@Override
	//与服务端相同
	public void channelConnected(ChannelHandlerContext ctx, ChannelStateEvent e)
			throws Exception {
		System.out.println("Hello World,I'm client");
	}
	
}


-----------------------------------------------------------------------------------------------------------------------------------------------------------------------------

最后符上前面提到的一篇博文的原文

Netty多线程处理机制

技术点描述

本文主要研究NioServerSocketChannelFactory类和NioDatagramChannelFactory类,

以及这两个类的各自作用。

由于基于pipelineFactory的线程池的配置已在前一节(Netty中execution包功能详解 )中做了详细说明,而channelFactory中的线程池的配置并未做说明,本文档重点阐述channelFactory的线程池配置。NioServerSocketChannelFactory主要应用于TCP协议的数据处理,NioDatagramChannelFactory主要应用于UDP协议的数据处理。

实现方案

简单介绍一下实现该功能,使用了哪些技术或知识点

参考源码包

以下是对这两个类的具体说明以及相关类,重要的常用的方法的说明

  1. NioServerSocketChannelFactory

此类常用于创建TCP的ServerBootstrap时作为构造方法的参数使用。

调用方式及设置如下:

ChannelFactory TCPCHANNEL_FACTORY = new NioServerSocketChannelFactory(

Executors.newCachedThreadPool(), Executors.newCachedThreadPool());

ServerBootstrap TCPSERVER_BOOTSTRAP = new ServerBootstrap(TCPCHANNEL_FACTORY);

基于NIO的用于创建服务器端channelchannelFactory,这个类利用非阻塞I/O模式引入NIO,这样可以有效地向多个并发连接提供Channel

线程的工作模式:

在此类中,有两种类型的线程,一种是boss线程,另一种是worker线程

Boss线程:

每个server服务器都会有一个boss线程,每绑定一个InetSocketAddress都会产生一个boss线程,比如:我们开启了两个服务器端口80和443,则我们会有两个boss线程。一个boss线程在端口绑定后,会接收传进来的连接,一旦连接接收成功,boss线程会指派一个worker线程处理连接。

Worker线程:

一个NioServerSocketChannelFactory会有一个或者多个worker线程。一个worker线程在非阻塞模式下为一个或多个Channels提供非阻塞 读或写

线程的生命周期和优雅的关闭

NioServerSocketChannelFactory被创建的时候,所有的线程都会从指定的Executors中获取。Boss线程从bossExecutor中获取,worker线程从workerExecutor中获取。因此,我们应该准确的指定Executors可以提供足够数量的线程,最好的选择就是指定一个cached线程池It is the best bet to specify a cached thread pool)。

此处发现所有源码中的例子(example)中均设置为Executors.newCachedThreadPool()

Boss线程和worker线程都是懒加载,没有程序使用的时候要释放掉。当boss线程和worker线程释放掉的时候,所有的相关资源如Selector也要释放掉。因此,如果想要优雅的关闭一个服务,需要做一下事情:

  1. factory创建的channels执行解绑(unbind)操作
  2. 关闭所有的由解绑的channels处理的子channels(这两步目前通常通过ChannelGroup.close()来操作)
  3. 调用releaseExternalResources()方法

请确保在所有的channels都关闭前不要关闭executor,否则,会报RejectedExecutionException异常而且相关资源可能不会被释放掉。

在此类中,最关键的构造方法:

public NioServerSocketChannelFactory(

Executor bossExecutor, WorkerPool<NioWorker> workerPool) {

if (bossExecutor == null) {

throw new NullPointerException("bossExecutor");

}

if (workerPool == null) {

throw new NullPointerException("workerPool");

}

this.bossExecutor = bossExecutor;

this.workerPool = workerPool;

sink = new NioServerSocketPipelineSink(workerPool);

}

参数说明:

bossExecutor:默认推荐设置为Executors.newCachedThreadPool()

workerPool:可通过new NioWorkerPool(workerExecutor, workerCount, true)创建,workerExecutor默认推荐设置为Executors.newCachedThreadPool()workerCount可设置为Runtime.getRuntime().availableProcessors() * 2(默认)

关于其中的NioWorkerPool类和NioServerSocketPipelineSink类,将在下文给予说明。

  1. NioWorkerPool

此类的关键方法是super的AbstractNioWorkerPool,

构造方法:

AbstractNioWorkerPool(Executor workerExecutor, int workerCount, boolean allowShutDownOnIdle) {

}

参数说明:

workerExecutor:worker线程的Executor

workerCount:最多创建的worker线程数

allowShutDownOnldle:空闲时是否关闭线程

  1. NioServerSocketPipelineSink

内部组件,传输服务的一个实现类,大多数情况下,不对用户开放。

  1. NioDatagramChannelFactory

此类常用于创建UDP的ServerBootstrap时作为构造方法的参数使用。

调用方式及设置如下:

ChannelFactory UDPCHANNEL_FACTORY = new NioDatagramChannelFactory()

ConnectionlessBootstrap UDPSERVER_BOOTSTRAP = new ConnectionlessBootstrap(UDPCHANNEL_FACTORY);

这个类利用非阻塞I/O模式引入NIO,这样可以有效地向多个并发连接提供Channel

此类仅有一种线程类型:worker线程。一个NioDatagramChannelFactory可创建一个或多个worker线程,一个worker线程在非阻塞模式下为一个或多个Channels提供非阻塞 读或写

在NioDatagramChannelFactory被创建的时候,所有的线程都会从指定的Executors中获取

因此,我们应该准确的指定Executors可以提供足够数量的线程,最好的选择就是指定一个cached线程池(It is the best bet to specify a cached thread pool)。

所有的worker线程都是懒加载,没有程序使用的时候要释放掉。当worker线程释放掉的时候,所有的相关资源如Selector也要释放掉。因此,如果想要优雅的关闭一个服务,需要做一下事情:

通常通过ChannelGroup.close()来关闭所有的由此factory创建的channels

调用releaseExternalResources()方法

请确保在所有的channels都关闭前不要关闭executor,否则,会报RejectedExecutionException异常而且相关资源可能不会被释放掉。

不支持多播模式,如果需要多播模式支持,采用OioDatagramChannelFactory替代

以下是此类中的最重要的构造方法:

public NioDatagramChannelFactory(WorkerPool<NioDatagramWorker> workerPool, InternetProtocolFamily family) {

}

参数说明:

workerPool:参考NioServerSocketChannelFactory

family:网络协议系列,这个参数是为了UDP的多播模式的,此参数只在java7+版本才有效。默认为null,可通过StandardProtocolFamily.INET(Ipv4)或者StandardProtocolFamily.INET6(Ipv6)设置

  1. NioClientSocketChannelFactory

与NioServerSocketChannelFactory类似,不做具体解说




分享到:
评论
1 楼 1058106015 2014-08-07  
噢耶,看到我的博客被引用了

相关推荐

    Netty之helloworld示列

    在本示例中,“Netty之helloworld”旨在为初学者提供一个简单的入门教程,帮助理解Netty的工作原理和基本用法。 首先,Netty的核心概念包括Bootstrap(引导类)、Channel(通道)、Handler(处理器)和EventLoop...

    基于NIO-EPOOL模型netty实现的具备一致性哈希算法的NAT端口映射器

    Netty是一个基于NIO的框架,它封装了底层复杂的NIO操作,提供了一套易于使用的API,使得开发者能够更专注于业务逻辑,而不是网络编程的细节。Netty支持多种传输协议,如TCP、UDP等,适合构建各种网络应用,如服务器...

    Java Netty-入门教程.pdf

    其中值得一提的是,Netty 的主要贡献者之一也是 Apache MINA(另一个流行的网络应用框架)的重要贡献者。这表明 Netty 在设计之初就吸收了大量来自 MINA 的经验教训,并在此基础上进行了创新和发展。 ##### 1.3 ...

    netty案例.zip

    Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。这个"netty案例.zip"压缩包提供了一个简单的Netty入门示例,帮助初学者理解如何使用Netty进行网络编程。下面...

    netty代码demo.rar

    Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。这个“netty代码demo.rar”文件很可能是包含了一些Netty的基础使用示例,帮助开发者理解和学习Netty的工作...

    netty学习教程

    - **定义**:Netty是由JBOSS提供的一个高性能的、异步的、事件驱动的网络应用框架,主要用于简化和加速高性能网络应用和服务的开发过程。 - **应用场景**: - 开发高性能的网络服务器与客户端。 - 构建分布式系统...

    Netty5.0架构剖析和源码解读

    Netty是一个高性能的网络应用程序框架,其核心优势在于异步事件驱动的I/O处理机制。接下来我们将深入分析Netty服务端的创建过程。 ###### 3.1.1. 服务端启动辅助类ServerBootstrap `ServerBootstrap`是Netty中创建...

    netty+protobuf入门案例.

    Netty是一个高性能、异步事件驱动的网络应用框架,用于快速开发可维护的高性能协议服务器和客户端。它提供了丰富的网络编程模型,简化了网络I/O操作,使得开发者可以更专注于业务逻辑的实现,而不是底层的连接管理和...

    Netty demos. (Netty 案例大全).zip

    Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。这个"Netty demos. (Netty 案例大全).zip"文件很可能包含了Netty 4.x版本的用户指南示例代码,帮助开发者更...

    Netty系列课程.zip

    Netty 是一个高性能、异步事件驱动的网络应用程序框架,用于快速开发可维护的高性能协议服务器和客户端。这个"Netty系列课程.zip"文件显然包含了关于Netty的详细教学资源,旨在帮助初学者快速入门并深入理解Netty的...

    深入浅出Netty

    标题:“深入浅出Netty”,意味着本文将采用由浅入深的方式,逐步揭开Netty这一强大网络框架的神秘面纱,帮助读者理解其核心概念与应用实践。 描述部分简述了文章的主旨,即通过详细介绍Netty的相关知识,使读者...

    netty学习笔记

    Netty是一个广泛使用的高性能、异步事件驱动的网络应用程序框架,它简化了网络编程的复杂性,使得开发者能够更轻松地开发高性能、高可靠性的网络服务器和客户端。Netty基于Java NIO (Non-blocking I/O) 技术构建,并...

    JAVA上百实例源码以及开源项目源代码

    数字证书:从文件中读取数字证书,生成文件输入流,输入文件为c:/mycert.cer,获取一个处理X.509证书的证书工厂…… Java+ajax写的登录实例 1个目标文件 内容索引:Java源码,初学实例,ajax,登录 一个Java+ajax写的...

    有关Java的Socket编程入门例子

    Java的Socket编程是网络编程的基础,它允许两个网络应用程序之间建立通信链接,进行数据传输。在Java中,Socket是java...实际开发中,还可以结合NIO(非阻塞I/O)或其他高级框架如Netty,提高网络通信的效率和灵活性。

    java精典编程100例

    - 为了提高服务器的并发处理能力,可以考虑使用NIO(非阻塞I/O)或者更高层次的框架如Netty。 ##### 2. Client编程 **定义:** 客户端编程主要是指应用程序与远程服务进行交互的过程。在Java中,客户端通常是通过...

    HelloWorld

    - **Netty**:高性能的NIO框架,适用于服务器端和客户端的应用程序,用于构建高并发的服务端应用。 - **ETL**、**Kafka**:用于处理大数据流,实现实时数据传输和处理。 - **服务治理平台**:监控和管理微服务集群的...

Global site tag (gtag.js) - Google Analytics