NIO-02:Reactor模式(二)

Java的NIO模式的Selector网络通讯,其实就是一个简单的Reactor模型。

下面是一个典型的NIO Reactor模型原型实现。

package com.lands.nio;

import java.io.IOException;
import java.net.InetAddress;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class SimpleServer {
	public static void testServer() throws IOException {

		// 创建Selector选择器
		Selector selector = Selector.open();

		// 创建服务端通道
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();

		// 服务端通道设置为非阻塞
		serverSocketChannel.configureBlocking(false);

		// 服务端通道绑定服务端口
		serverSocketChannel.bind(new InetSocketAddress(InetAddress.getLocalHost(), 7777));

		// 将选择器和ACCEPT事件注册到服务端通道上
		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

		// 采用阻塞式轮询的方式,监听获取服务端通道上注册的事件
		while (selector.select() > 0) {

			// 获取当前选择器监听到的所有事件KEY
			Iterator<SelectionKey> selectedKeys = selector.selectedKeys().iterator();

			while (selectedKeys.hasNext()) {

				// 逐一识别事件KEY
				SelectionKey selectedKey = selectedKeys.next();

				// 是否为ACCEPT事件(连接就绪事件)
				if (selectedKey.isAcceptable()) {

					// 建立客户端通道连接
					SocketChannel socketChannel = serverSocketChannel.accept();

					// 切换为非阻塞模式
					socketChannel.configureBlocking(false);

					// 为客户端通道注册选择器和READ事件(读就绪事件)
					socketChannel.register(selector, SelectionKey.OP_READ);

				} else if (selectedKey.isReadable()) {
					// 如果是READ事件(读就绪事件),获取该选择器上的“读就绪”状态的客户端通道
					SocketChannel socketChannel = (SocketChannel) selectedKey.channel();

					// 读取数据,建立缓冲区
					ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
					int length = 0;
					while ((length = socketChannel.read(byteBuffer)) != -1) {
						//确定当前缓冲区的有效数据,为数据输出做准备。flip缓冲区回针操作。
						byteBuffer.flip();
						
						//输出缓冲区中的数据
						System.out.println(new String(byteBuffer.array(), 0, length));
						
						//复位缓冲区的所有标志位,为下一次Readable事件做准备
						byteBuffer.clear();
					}
					socketChannel.close();
				}

				//移除所有选择键
				selectedKeys.remove();
			}
			
		} // while (selector.select() > 0)

		//关闭连接
		serverSocketChannel.close();
	}

	public static void main(String[] args) throws IOException {
		testServer();
	}
}
package com.lands.nio;

import java.io.BufferedWriter;
import java.io.OutputStream;
import java.io.PrintWriter;
import java.net.InetAddress;
import java.net.Socket;

public class Client {

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

		// 1.创建客户端Socket,指定服务器地址和端口
		Socket so = new Socket(InetAddress.getLocalHost(), 7777);// 端口号要和服务器端相同

		// 2.获取输出流,向服务器端发送登录的信息
		OutputStream os = so.getOutputStream();// 字节输出流

		PrintWriter pw = new PrintWriter(os);// 字符输出流

		BufferedWriter bw = new BufferedWriter(pw);// 加上缓冲流

		bw.write("用户名:admin;密码:123");

		bw.flush();

		so.shutdownOutput();// 关闭输出流

		// 3.关闭资源
		bw.close();
		pw.close();
		os.close();
		so.close();
	}

}

实际上的Reactor模式,是基于Java NIO的,在他的基础上,抽象出来两个组件——Reactor和Handler两个组件:

(1)Reactor:负责响应IO事件,当检测到一个新的事件,将其发送给相应的Handler去处理;新的事件包含连接建立就绪、读就绪、写就绪等。

(2)Handler:将自身(handler)与事件绑定,负责事件的处理,完成channel的读入,完成处理业务逻辑后,负责将结果写出channel。

 

转载于:https://my.oschina.net/blacklands/blog/3090042

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值