nio,一般的reactor,Mina的Reactor

12 篇文章 0 订阅

nio:

    一个简单的nioserver。启动后,在浏览器输入:http://localhost:1234。就可以看到http的请求。

public class Test<T> implements Callable<T> {
	private Selector selector;// 创建全局selector

	public Test() throws IOException {
		selector = Selector.open();
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
		serverSocketChannel.configureBlocking(false);
		serverSocketChannel.socket().bind(new InetSocketAddress(1234));
		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
	}

	public T call() throws Exception {
		for (;;) {

			if (selector.select(1000) == 0) {
				continue;
			}

			Iterator<SelectionKey> keyIterator = selector.selectedKeys()
					.iterator();

			while (keyIterator.hasNext()) {
				SelectionKey key = keyIterator.next();
				if (key.isAcceptable()) {
					SocketChannel clientChannel = ((ServerSocketChannel) key
							.channel()).accept();
					clientChannel.configureBlocking(false);
					clientChannel
							.register(key.selector(), SelectionKey.OP_READ);
				}

				if (key.isReadable()) {
					// 获得与客户端通信的信道
					SocketChannel clientChannel = (SocketChannel) key.channel();

					// 得到并重置缓冲区的主要索引值
					ByteBuffer buffer = (ByteBuffer) key.attachment();
					buffer.clear();

					// 读取信息获得读取的字节数
					long bytesRead = clientChannel.read(buffer);

					if (bytesRead == -1) {
						// 没有读取到内容的情况
						clientChannel.close();
					} else {
						// 将缓冲区准备为数据传出状态
						buffer.flip();

						// 将获得字节字符串(使用Charset进行解码)
						String receivedString = Charset.forName("utf-8")
								.newDecoder().decode(buffer).toString();

						// 控制台打印出来
						System.out.println("接收到信息:" + receivedString);

						// 准备发送的文本
						String sendString = "你好,客户端. 已经收到你的信息" + receivedString;

						// 将要发送的字符串编码(使用Charset进行编码)后再进行包装
						buffer = ByteBuffer.wrap(sendString.getBytes("utf-8"));

						// 发送回去
						clientChannel.write(buffer);

						// 设置为下一次读取或是写入做准备
						key.interestOps(SelectionKey.OP_READ
								| SelectionKey.OP_WRITE);
					}
				}

				keyIterator.remove();
			}
		}
	}

	public static void main(String args[]) throws IOException, Exception {
		new Test().call();
	}
}

Reactor模式:

     1.Reactor 负责响应IO事件,一旦发生,广播发送给相应的Handler去处理。
   2.Handler 是负责非堵塞行为。

public class Reactor implements Runnable{

	final Selector selector;
	final ServerSocketChannel serverSocket;
	
	ExecutorService pool = Executors.newFixedThreadPool(3);

	public Reactor(int port) throws IOException {
		selector = Selector.open();
		serverSocket = ServerSocketChannel.open();
		InetSocketAddress address = new InetSocketAddress(port);
		serverSocket.socket().bind(address);
		serverSocket.configureBlocking(false);
		
		// 向selector注册该channel
		SelectionKey sk = serverSocket.register(selector,
				SelectionKey.OP_ACCEPT);


		// 利用sk的attache功能绑定Acceptor 如果有事情,触发Acceptor
		sk.attach(new Acceptor());
	}

	void dispatch(SelectionKey k) {
		Runnable r = (Runnable) (k.attachment());
		r.run();
	}

	public void run() {
		try {
			while (true) {
				int temp = selector.select();
				Iterator<SelectionKey> keyIter = selector.selectedKeys()
						.iterator();
				while (keyIter.hasNext()) {
					SelectionKey key = keyIter.next();
					keyIter.remove();
					
					dispatch(key);
				}
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}
	
	class Acceptor implements Runnable {

		public void run() {
			try {
				SocketChannel c = serverSocket.accept();
				if (c != null)
					pool.execute(new SocketReadHandler(selector, c));
			} catch (IOException e) {
				e.printStackTrace();
			}
		}

	}

	public static void main(String args[]) throws IOException {
		new Reactor(1234).run();
	}
}

public class SocketReadHandler implements Runnable {
	public static Logger logger = Logger.getLogger("SocketReadHandler");

	final SocketChannel sc;
	final SelectionKey sk;

	ByteBuffer input = ByteBuffer.allocate(1024);
	ByteBuffer output = ByteBuffer.allocate(1024);

	static final int READING = 0, SENDING = 1;
	int state = READING;

	public SocketReadHandler(Selector sel, SocketChannel sc) throws IOException {
		this.sc = sc;
		sc.configureBlocking(false);
		sk = sc.register(sel, 0);
		// 将SelectionKey绑定为本Handler 下一步有事件触发时,将调用本类的run方法。
		// 参看dispatch(SelectionKey k)
		sk.attach(this);
		// 同时将SelectionKey标记为可读,以便读取。
		sk.interestOps(SelectionKey.OP_READ);
		sel.wakeup();
	}

	public void run() {
		try {
			if (state == READING) {
				read();
			} else if (state == SENDING) {
				send();
			}
		} catch (IOException e) {
			e.printStackTrace();
		}
	}

	private void send() throws IOException {
		sc.write(output);
		sk.cancel();
	}

	private void read() throws IOException {
		long bytesRead = sc.read(input);

		if (bytesRead == -1) {
			sc.close();
		} else {
			input.flip();
			String receivedString = Charset.forName("utf-8").newDecoder()
					.decode(input).toString();
			// 控制台打印出来
			System.out.println("接收到信息:" + receivedString);
			
			state = SENDING;
			sk.interestOps(SelectionKey.OP_WRITE);
		}
	}

}


      上面代码改编自《Reactor模式和NIO》,详见参考资料。

      SocketChannel的attach功能,将Hanlder和可能会发生事件的channel链接在一起,当发生事件时,可以立即触发相应链接的Handler。增加了一个线程池

Mina的Reator:

     

    与传统的单个Reactor模式实现不同,mina中采用了Multiple Reactor的方式。NioSocketAcceptor和NioProcessor使用不同selector,能够更加充分的榨取服务器的性能。 

acctptor主要负责 
1. 绑定一个/多个端口,开始监听 
2. 处理客户端的建链请求 
3. 关闭一个/多个监听端口 
processor主要负责 
1. 接受客户端发送的数据,并转发给业务逻辑成处理 
2. 发送数据到客户端 

   mina的reactor模式详见mina1.0.10的源码:http://mina.apache.org/dyn/closer.cgi/mina/1.0.10/mina-1.0.10.zip





参考资料:

uniseraph:http://uniseraph.iteye.com/blog/228221——《【mina指南】mina中的reactor模式(一)》

uniseraph:http://uniseraph.iteye.com/blog/229130——《【mina指南】mina中的reactor模式(二)

何杨http://www.blogjava.net/heyang/archive/2011/01/03/342193.html——《Java NIO 服务器端简单实现例子

板桥里人:http://www.jdon.com/concurrent/reactor.htm——《Reactor模式和NIO

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 2
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值