Java NIO——5 基于非阻塞编程NIO的例子

之前,写的大多都是一些NIO知识点,没有贴出实例,可能看起来比较晦涩,下面是一个基于非阻塞的nio实例

Server:

/**
 * 服务器端
 * 
 * @author Joeson
 * 
 */
public class MyServer
{

	public static void main(String args[]) throws Exception
	{
		MyServer server = new MyServer(8080);
		server.listen();
	}

	// 接受和发送数据缓冲区
	private ByteBuffer send = ByteBuffer.allocate(1024);
	private ByteBuffer receive = ByteBuffer.allocate(1024);

	public int port = 0;

	ServerSocketChannel ssc = null;

	Selector selector = null;

	public MyServer(int port) throws Exception
	{
		// 打开服务器套接字通道
		ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
		// 服务器配置为非阻塞
		serverSocketChannel.configureBlocking(false);
		// 检索与此通道关联的服务器套接字
		ServerSocket serverSocket = serverSocketChannel.socket();
		// 进行服务的绑定
		serverSocket.bind(new InetSocketAddress(port));
		// 通过open()方法找到Selector
		selector = Selector.open();

		// 注册到selector,等待连接
		serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);
		System.out.println("Server Start----8888:");
		
		// 向发送缓冲区加入数据
		send.put("data come from server".getBytes());
	}

	// 监听
	private void listen() throws IOException
	{
		while (true)
		{
			// 选择一组键,并且相应的通道已经打开
			selector.select();
			// 返回此选择器的已选择键集。
			Set<SelectionKey> selectionKeys = selector.selectedKeys();
			Iterator<SelectionKey> iterator = selectionKeys.iterator();
			while (iterator.hasNext())
			{
				SelectionKey selectionKey = iterator.next();

				// 这里记得手动的把他remove掉,不然selector中的selectedKeys集合不会自动去除
				iterator.remove();
				dealKey(selectionKey);
			}
		}
	}

	// 处理请求
	private void dealKey(SelectionKey selectionKey) throws IOException
	{

		ServerSocketChannel server = null;
		SocketChannel client = null;
		String receiveText;
		String sendText;
		int count = 0;

		// 测试此键的通道是否已准备好接受新的套接字连接。
		if (selectionKey.isAcceptable())
		{
			// 返回为之创建此键的通道。
			server = (ServerSocketChannel) selectionKey.channel();

			// 此方法返回的套接字通道(如果有)将处于阻塞模式。
			client = server.accept();
			// 配置为非阻塞
			client.configureBlocking(false);
			// 注册到selector,等待连接
			client.register(selector, SelectionKey.OP_READ
					| SelectionKey.OP_WRITE);
		}
		else
			if (selectionKey.isReadable())
			{
				// 返回为之创建此键的通道。
				client = (SocketChannel) selectionKey.channel();
				// 将缓冲区清空以备下次读取
				receive.clear();
				// 读取服务器发送来的数据到缓冲区中
				client.read(receive);

				System.out.println(new String(receive.array()));
				
				selectionKey.interestOps(SelectionKey.OP_WRITE);
			}
			else
				if (selectionKey.isWritable())
				{
					// 将缓冲区清空以备下次写入
					send.flip();
					// 返回为之创建此键的通道。
					client = (SocketChannel) selectionKey.channel();

					// 输出到通道
					client.write(send);
					
					selectionKey.interestOps(SelectionKey.OP_READ);
				}
	}
}

Client:

/**
 * 客户端
 * 
 * @author Joeson
 * 
 */
public class MyClient
{
	public static void main(String args[])
	{
		try
		{
			MyClient client = new MyClient();
			client.work(8085);
		} catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}
	}

	SocketChannel sc = null;

	Selector selector = null;

	// 发送接收缓冲区
	ByteBuffer send = ByteBuffer.wrap("data come from client".getBytes());
	ByteBuffer receive = ByteBuffer.allocate(1024);

	public void work(int port) throws IOException
	{

		try
		{
			sc = SocketChannel.open();
			selector = selector.open();

			// 注册为非阻塞通道
			sc.configureBlocking(false);

			sc.connect(new InetSocketAddress("localhost", 8080));

			sc.register(selector, SelectionKey.OP_CONNECT|SelectionKey.OP_READ|SelectionKey.OP_WRITE);

		} catch (IOException e)
		{
			// TODO Auto-generated catch block
			e.printStackTrace();
		}

		// Set<SelectionKey> selectionKeys = null;
		while (true)
		{
			// 选择
			if (selector.select() == 0)
			{
				continue;
			}

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

			while (it.hasNext())
			{
				SelectionKey key = it.next();

				// 必须由程序员手动操作
				it.remove();
				
				sc = (SocketChannel) key.channel();

				if (key.isConnectable())
				{
					if (sc.isConnectionPending())
					{
						// 结束连接,以完成整个连接过程
						sc.finishConnect();
						System.out.println("connect completely");

						try
						{
							sc.write(send);
						} catch (IOException e)
						{
							// TODO Auto-generated catch block
							e.printStackTrace();
						}
						
//						sc.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
					}

				}
				else
					if (key.isReadable())
					{
						try
						{
							receive.clear();

							sc.read(receive);

							System.out.println(new String(receive.array()));

						} catch (IOException e)
						{
							// TODO Auto-generated catch block
							e.printStackTrace();
						}

					}
					else
						if (key.isWritable())
						{
							receive.flip();
							try
							{
								send.flip();
								
								sc.write(send);
							} catch (IOException e)
							{
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}

			}// end while

		}// end while(true)

	}// end work()

}

评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值