关于NIO以及简单DEMO

今天脑袋里突然冒出来NIO 所以记录一下

定义:什么是NIO 即 NOBLOCKING IO  与IO 有相同作用与目的  关于什么是IO本文不作解释

IO是以流的方式处理数据 NIO是以块的方式处理数据

关键:  Buffer Channel Selector 简介

Buffer:包含了写入或读出的数据 在NIO中 数据是放在Buffer对象中的,程序不能直接对数据进行操作必须用buffer来进行操作。也就是说 Channel 通过buffer来读写数据。

Channel :可以通过Channel 读取和写入数据,类似流,但是与流不同的是 Channel 是双向的既能读又能写 还可以进行异步的读写  对Channel的读写必须通过buffer对象。

Selector:可以注册到多个Channel 上,监听各个Channel 发生的事件,根据事件定义情况决定Channel 读写

写了个步骤简单例子:

/**
 * 服务器端
 * */
public class NioSrver {

	public void start() throws IOException {
		/**
		 * 1.创建seletor
		 * */
		Selector selector = Selector.open();
		/**
		 * 2.通过serversocketChannel创建channel通道
		 * */
		ServerSocketChannel channel = ServerSocketChannel.open();
		/**
		 * 3.为channel绑定监听端口
		 * */
		channel.bind(new InetSocketAddress(9876));
		/**
		 * 4.设置channel为非阻塞模式
		 * */
		channel.configureBlocking(false);
		/**
		 * 5.将channel注册到selector上 监听连接事件
		 * */
		channel.register(selector, SelectionKey.OP_ACCEPT);
		
		/**
		 * 6.循环等待新接入连接
		 * */
		for (;;) {
			// 获取可用channel数量
			int readychannels = selector.select();
			// 没有可用channel数量跳出
			if (readychannels == 0)
				continue;
			// 获取可用channel集合
			Set<SelectionKey> selectedKeys = selector.selectedKeys();
			Iterator iterator = selectedKeys.iterator();
			while (iterator.hasNext()) {
				SelectionKey key = (SelectionKey) iterator.next();
				iterator.remove();
				/**
				 * 7.根据就绪状态 调用对应方法处理业务逻辑
				 * */
				// 如果是接入事件
				if (key.isAcceptable()) {
					acceptHandler(channel, selector);
				}
				// 如果是可读事件
				if (key.isReadable()) {
					readHandler(key, selector);
				}
			}

		}
	}

	/**
	 * 接入事件处理器
	 * */
	private void acceptHandler(ServerSocketChannel serverSocketChannel,
			Selector selector) throws IOException {

		// 如果是接入事件 创建socketChannel
		SocketChannel socketChannel = serverSocketChannel.accept();
		// 将socketChannel设为非阻塞模式
		socketChannel.configureBlocking(false);
		// 将socketChannel注册到selector上 监听可读事件
		socketChannel.register(selector, SelectionKey.OP_READ);
		// 回复客户端信息
		socketChannel.write(Charset.forName("utf-8").encode("连接成功"));
	}

	/**
	 * 可读事件处理器
	 * */
	private void readHandler(SelectionKey selectionKey, Selector selector)
			throws IOException {
		// 从SelectionKey中 获取到已经就绪的channel 当前要处理的channel
		SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
		// 创建buffer
		ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
		// 循环客户端请求
		String request = "";
		while (socketChannel.read(byteBuffer) > 0) {
			// 切换byteBuffer为读模式
			byteBuffer.flip();
			// 读取byteBuffer中的内容
			request += Charset.forName("UTF-8").decode(byteBuffer);
		}
		// 再次将channel注册到selector上
		socketChannel.register(selector, selectionKey.OP_READ);
		// 将客户端发送的请求信息 广播给其他客户端
		if (request.length() > 0) {
			/*brodCast(selector, socketChannel, request);*/
			System.out.println("-----");
		}
	}

	/**
	 * 广播给其他客户端
	 */
	private void brodCast(Selector selector,SocketChannel socketChannel
			,String request)throws IOException{
		//获取所有已经接入的客户端channel
		Set<SelectionKey>selectionKeySet = selector.keys();
		//循环向channel广播信息
		for (SelectionKey selectionKey : selectionKeySet) {
			Channel targetChannel = selectionKey.channel();
			if(targetChannel instanceof SocketChannel
					&& targetChannel!=socketChannel){
				((SocketChannel)targetChannel).write(Charset.forName("UTF-8").encode(request));
			}
		}
	}

	public static void main(String[] args) {
		try {
			new NioSrver().start();
		} catch (IOException e) {
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}
}
/**
 * NIO客户端
 * */
public class NioClient {

	/**
	 * 启动
	 * */
	public  void start(String name) throws IOException {
		/**
		 * 连接服务器端
		 * */
		SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress(
				"127.0.0.1", 9876));
		/**
		 * 接收服务端响应
		 * */
		// 新建线程 专门负责接收服务器端的相应数据
		Selector selector = Selector.open();
		socketChannel.configureBlocking(false);
		socketChannel.register(selector, SelectionKey.OP_READ);
		new Thread(new NioClientHandler(selector)).start();
		/**
		 * 向服务器发送数据
		 * */
		Scanner sc = new Scanner(System.in);
		String request = sc.nextLine();
		while (sc.hasNextLine()) {
			if (request != null && request.length() > 0) {
				socketChannel.write(Charset.forName("UTF-8").encode(name+":"+request));
			}
		}
	}
}
/**
 * 客户端线程类 专门负责接收服务器端响应信息
 * */
public class NioClientHandler implements Runnable {
	private Selector selector;

	public NioClientHandler(Selector selector) {
		this.selector = selector;
	}

	@Override
	public void run() {
		try {
			// TODO Auto-generated method stub
			for (;;) {
				// 获取可用channel数量
				int readychannels = selector.select();
				// 没有可用channel数量跳出
				if (readychannels == 0)
					continue;
				// 获取可用channel集合
				Set<SelectionKey> selectedKeys = selector.selectedKeys();
				Iterator iterator = selectedKeys.iterator();
				while (iterator.hasNext()) {
					SelectionKey key = (SelectionKey) iterator.next();
					iterator.remove();
					/**
					 * 7.根据就绪状态 调用对应方法处理业务逻辑
					 * */
					// 如果是可读事件
					if (key.isReadable()) {
						readHandler(key, selector);
					}
				}

			}
		} catch (IOException e) {

		}
	}

	/**
	 * 可读事件处理器
	 * */
	private void readHandler(SelectionKey selectionKey, Selector selector)
			throws IOException {
		// 从SelectionKey中 获取到已经就绪的channel 当前要处理的channel
		SocketChannel socketChannel = (SocketChannel) selectionKey.channel();
		// 创建buffer
		ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
		// 循环服务器端响应信息
		String response = "";
		while (socketChannel.read(byteBuffer) > 0) {
			// 切换byteBuffer为读模式
			byteBuffer.flip();
			// 读取byteBuffer中的内容
			response += Charset.forName("UTF-8").decode(byteBuffer);
		}
		// 再次将channel注册到selector上
		socketChannel.register(selector, selectionKey.OP_READ);
		// 将服务端响应信息打印到本地
		if (response.length() > 0) {
			System.out.println(response);
		}
	}

}

 

public class ClientA {
	
	public static void main(String[] args)throws IOException{
		new NioClient().start("腿腿");
	}
	

}
public class ClientB {

	public static void main(String[] args)throws IOException{
		new NioClient().start("球球");
	}
}
public class ClientC {
	public static void main(String[] args)throws IOException{
		new NioClient().start("蘑菇头");
	}

}

就这样吧 记录一下 主要是记录使用步骤 按照1-7的步骤去做便于记忆。就酱。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值