JAVA高级基础(52)---非阻塞式的IO通信

版权声明:如需转载请标明出处 https://blog.csdn.net/yj201711/article/details/84956423

非阻塞式

客户端

  1. 获取通道
  2. 切换非阻塞模式
  3. 分配指定大小的缓冲区
  4. 发送数据给服务端
  5. 关闭通道 

服务端

  1. 获取通道
  2. 切换非阻塞模式
  3. 绑定连接
  4. 获取选择器
  5. 将通道注册到选择器上, 并且指定“监听接收事件”
  6. 轮询式的获取选择器上已经“准备就绪”的事件
  7. 获取当前选择器中所有注册的“选择键(已就绪的监听事件)”
  8. 获取准备“就绪”的是事件
  9. 判断具体是什么事件准备就绪
  10. 若“接收就绪”,获取客户端连接
  11. 切换非阻塞模式
  12. 将该通道注册到选择器上
  13. 获取当前选择器上“读就绪”状态的通道
  14. 读取数据
package org.lanqiao.nonblocking.demo;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;

/*
 * 客户端:
	1. 获取通道
	2. 切换非阻塞模式
	3. 分配指定大小的缓冲区
	4. 发送数据给服务端
	5. 关闭通道

 */
public class Client {
	public static void main(String[] args) throws IOException {
		SocketChannel sChannel = SocketChannel.open(new InetSocketAddress("127.0.0.1", 9999));
		//sChannel.bind(new InetSocketAddress("127.0.0.1", 9999));
		//切换非阻塞式
		sChannel.configureBlocking(false);
		//System.out.println(sChannel.isBlocking());
		ByteBuffer buf = ByteBuffer.allocate(1024);
		FileChannel fChannel = FileChannel.open(Paths.get("aa.jpg"), StandardOpenOption.READ);
		while(fChannel.read(buf) != -1) {
			buf.flip();
			sChannel.write(buf);
			buf.clear();
		}
		sChannel.close();
		fChannel.close();
	}
}
package org.lanqiao.nonblocking.demo;

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.FileChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SocketChannel;
import java.nio.file.Paths;
import java.nio.file.StandardOpenOption;
import java.util.Iterator;
import java.util.Set;

public class Server {
	public static void main(String[] args) throws IOException {
//		  1. 获取通道
		ServerSocketChannel ssChannel  = ServerSocketChannel.open();
		ByteBuffer buf = ByteBuffer.allocate(1024);
		FileChannel fChannel = FileChannel.open(Paths.get("copy.jpg"), StandardOpenOption.WRITE,StandardOpenOption.CREATE);	
//		  2. 切换非阻塞模式
		ssChannel.configureBlocking(false);
//		  3. 绑定连接
		ssChannel.bind(new InetSocketAddress(9999));
//		  4. 获取选择器
		Selector select = Selector.open();
//		  5. 将通道注册到选择器上, 并且指定“监听接收事件”
		ssChannel.register(select, SelectionKey.OP_ACCEPT);
//		  6. 轮询式的获取选择器上已经“准备就绪”的事件
		while(select.select() > 0) {
//			  7. 获取当前选择器中所有注册的“选择键(已就绪的监听事件)”
			Set<SelectionKey>  skSet =  select.selectedKeys();
//			  8. 获取准备“就绪”的是事件
			Iterator<SelectionKey> iter = skSet.iterator();
//			  9. 判断具体是什么事件准备就绪
			while(iter.hasNext()) {
				SelectionKey sk = iter.next();
//				  10. 若“接收就绪”,获取客户端连接	
				if(sk.isAcceptable()) {
				SocketChannel  sChannel = 	ssChannel.accept();
//					  11. 切换非阻塞模式
				sChannel.configureBlocking(false);
//				  12. 将该通道注册到选择器上		
				sChannel.register(select, SelectionKey.OP_READ);

//				  13. 获取当前选择器上“读就绪”状态的通道				
				}else if(sk.isReadable()) {
				SocketChannel sokcetCh = 	(SocketChannel) sk.channel();
//						  14. 读取数据	
						while(sokcetCh.read(buf) != -1) {
							buf.flip();
							fChannel.write(buf);
							buf.clear();
							
						}
						
					}
			}
			iter.remove();//将注册再该选择器上的通道进行移除	
			}

	}
}

猜你喜欢

转载自blog.csdn.net/yj201711/article/details/84956423
今日推荐