文档章节

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

chaun
 chaun
发布于 2015/04/22 18:31
字数 697
阅读 75
收藏 0

之前,写的大多都是一些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()

}



本文转载自:http://blog.csdn.net/chenxuegui1234/article/details/17979725

chaun
粉丝 92
博文 271
码字总数 91117
作品 0
深圳
高级程序员
私信 提问
Qzone 微信 Java高级——dubbo源码分析之远程通信 netty

Java高级——dubbo源码分析之远程通信 netty dubbo 底层通信选择了 netty 这个 nio 框架做为默认的网络通信框架并且通过自定义协议进行通信。dubbo 支持以下网络通信框架: Netty(默认) Min...

Java架构师那些事
2018/08/29
0
0
少啰嗦!一分钟带你读懂Java的NIO和经典IO的区别

本文引用了“架构师社区”公众号的《史上讲的最好的Java NIO与IO的区别与应用》一文部分内容,感谢原作者的技术分享。 1、引言 很多初涉网络编程的程序员,在研究Java NIO(即异步IO)和经典...

JackJiang2011
06/25
0
0
Linux IO模型与Java NIO

概述 看Java NIO一篇文章的时候又看到了“异步非阻塞”这个概念,一直处于似懂非懂的状态,想解释下到底什么是异步 什么是非阻塞,感觉抓不住重点。决定仔细研究一下。 本文试图研究以下问题...

yingtju
2018/06/29
0
0
Java NIO 系列教程 -- delete

(一) Java NIO 概述 Java NIO 由以下几个核心部分组成: Channels Buffers Selectors 虽然Java NIO 中除此之外还有很多类和组件,但在我看来,Channel,Buffer 和 Selector 构成了核心的A...

数据之美
2013/06/09
0
4
Java网络编程框架

自从JDK1.4中有了NIO以后,这个方面越来越活跃,也为java赢得更多开发者的支持。做java网络编程需要掌握一些基本的知识和技能: 套接字编程、阻塞/非阻塞通信、创建HTTP服务器与客户程序、数...

长平狐
2012/08/29
2.3K
0

没有更多内容

加载失败,请刷新页面

加载更多

JS其他类型值转化为Boolean类型规则

本文转载于:专业的前端网站➤JS其他类型值转化为Boolean类型规则 由于最近在笔试的时候,发现好多关于其他类型转化为Boolean类型的题目,因此总结一下! 一、String类型转化为Boolean 1.转化...

前端老手
25分钟前
4
0
EurekaClient自动装配及启动流程解析

在上篇文章中,我们简单介绍了EurekaServer自动装配及启动流程解析,本篇文章则继续研究EurekaClient的相关代码 老规矩,先看spring.factories文件,其中引入了一个配置类EurekaDiscoveryClie...

Java学习录
31分钟前
5
0
析构函数是否必须为虚函数?为何?

在C++中,基类指针可以指向一个派生类的对象。如果基类的析构函数不是虚函数,当需要delete这个指向派生类的基类指针时,就只会调用基类的析构函数,而派生类的析构函数无法被调用。容易造成...

天王盖地虎626
32分钟前
4
0
【TencentOS tiny】深度源码分析(7)——事件

引言 大家在裸机编程中很可能经常用到flag这种变量,用来标志一下某个事件的发生,然后在循环中判断这些标志是否发生,如果是等待多个事件的话,还可能会if((xxx_flag)&&(xxx_flag))这样子做...

杰杰1号
35分钟前
6
0
聊聊nacos client的ServerHttpAgent

序 本文主要研究一下nacos client的ServerHttpAgent HttpAgent nacos-1.1.3/client/src/main/java/com/alibaba/nacos/client/config/http/HttpAgent.java public interface HttpAgent { ......

go4it
41分钟前
5
0

没有更多内容

加载失败,请刷新页面

加载更多

返回顶部
顶部