- 浏览: 395355 次
- 性别:
- 来自: 杭州
博客专栏
-
Spring技术内幕读书笔...
浏览量:15658
文章分类
最新评论
-
albert0707:
非常感谢!
JAVA NIO 实例 -
greatwqs:
表露清晰, 言简意赅, 重新温习了一次
MySQL事务隔离级别详解 -
lgh1992314:
新版本都不需要了。ServiceLoader<Drive ...
DriverManager和Class.forName()的异同 -
zipmoon:
像以上的实验,就没有出现数据幻读的问题。 ---原因:My ...
MySQL事务隔离级别详解 -
jnjeC:
贴代码来了。大家还要根据代码做一定的修改。########## ...
MySQL事务隔离级别详解
最近一直在忙着JAVA NIO的知识,花了一下午的时间,总算写出了一个可以运行的程序,废话少说,上代码!
import java.io.IOException; import java.net.InetSocketAddress; import java.net.ServerSocket; 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; import java.util.Set; public class NIOServer { /*标识数字*/ private int flag = 0; /*缓冲区大小*/ private int BLOCK = 4096; /*接受数据缓冲区*/ private ByteBuffer sendbuffer = ByteBuffer.allocate(BLOCK); /*发送数据缓冲区*/ private ByteBuffer receivebuffer = ByteBuffer.allocate(BLOCK); private Selector selector; public NIOServer(int port) throws IOException { // 打开服务器套接字通道 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:"); } // 监听 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(); iterator.remove(); handleKey(selectionKey); } } } // 处理请求 private void handleKey(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); } else if (selectionKey.isReadable()) { // 返回为之创建此键的通道。 client = (SocketChannel) selectionKey.channel(); //将缓冲区清空以备下次读取 receivebuffer.clear(); //读取服务器发送来的数据到缓冲区中 count = client.read(receivebuffer); if (count > 0) { receiveText = new String( receivebuffer.array(),0,count); System.out.println("服务器端接受客户端数据--:"+receiveText); client.register(selector, SelectionKey.OP_WRITE); } } else if (selectionKey.isWritable()) { //将缓冲区清空以备下次写入 sendbuffer.clear(); // 返回为之创建此键的通道。 client = (SocketChannel) selectionKey.channel(); sendText="message from server--" + flag++; //向缓冲区中输入数据 sendbuffer.put(sendText.getBytes()); //将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位 sendbuffer.flip(); //输出到通道 client.write(sendbuffer); System.out.println("服务器端向客户端发送数据--:"+sendText); client.register(selector, SelectionKey.OP_READ); } } /** * @param args * @throws IOException */ public static void main(String[] args) throws IOException { // TODO Auto-generated method stub int port = 8888; NIOServer server = new NIOServer(port); server.listen(); } }
import java.io.IOException; import java.net.InetSocketAddress; import java.nio.ByteBuffer; import java.nio.channels.SelectionKey; import java.nio.channels.Selector; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.Set; public class NIOClient { /*标识数字*/ private static int flag = 0; /*缓冲区大小*/ private static int BLOCK = 4096; /*接受数据缓冲区*/ private static ByteBuffer sendbuffer = ByteBuffer.allocate(BLOCK); /*发送数据缓冲区*/ private static ByteBuffer receivebuffer = ByteBuffer.allocate(BLOCK); /*服务器端地址*/ private final static InetSocketAddress SERVER_ADDRESS = new InetSocketAddress( "localhost", 1111); public static void main(String[] args) throws IOException { // TODO Auto-generated method stub // 打开socket通道 SocketChannel socketChannel = SocketChannel.open(); // 设置为非阻塞方式 socketChannel.configureBlocking(false); // 打开选择器 Selector selector = Selector.open(); // 注册连接服务端socket动作 socketChannel.register(selector, SelectionKey.OP_CONNECT); // 连接 socketChannel.connect(SERVER_ADDRESS); // 分配缓冲区大小内存 Set<SelectionKey> selectionKeys; Iterator<SelectionKey> iterator; SelectionKey selectionKey; SocketChannel client; String receiveText; String sendText; int count=0; while (true) { //选择一组键,其相应的通道已为 I/O 操作准备就绪。 //此方法执行处于阻塞模式的选择操作。 selector.select(); //返回此选择器的已选择键集。 selectionKeys = selector.selectedKeys(); //System.out.println(selectionKeys.size()); iterator = selectionKeys.iterator(); while (iterator.hasNext()) { selectionKey = iterator.next(); if (selectionKey.isConnectable()) { System.out.println("client connect"); client = (SocketChannel) selectionKey.channel(); // 判断此通道上是否正在进行连接操作。 // 完成套接字通道的连接过程。 if (client.isConnectionPending()) { client.finishConnect(); System.out.println("完成连接!"); sendbuffer.clear(); sendbuffer.put("Hello,Server".getBytes()); sendbuffer.flip(); client.write(sendbuffer); } client.register(selector, SelectionKey.OP_READ); } else if (selectionKey.isReadable()) { client = (SocketChannel) selectionKey.channel(); //将缓冲区清空以备下次读取 receivebuffer.clear(); //读取服务器发送来的数据到缓冲区中 count=client.read(receivebuffer); if(count>0){ receiveText = new String( receivebuffer.array(),0,count); System.out.println("客户端接受服务器端数据--:"+receiveText); client.register(selector, SelectionKey.OP_WRITE); } } else if (selectionKey.isWritable()) { sendbuffer.clear(); client = (SocketChannel) selectionKey.channel(); sendText = "message from client--" + (flag++); sendbuffer.put(sendText.getBytes()); //将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位 sendbuffer.flip(); client.write(sendbuffer); System.out.println("客户端向服务器端发送数据--:"+sendText); client.register(selector, SelectionKey.OP_READ); } } selectionKeys.clear(); } } }
个人感觉,JAVA NIO的操作时麻烦了不少,但是无疑这样做效率会得到很大的提升。
评论
22 楼
albert0707
2018-06-29
非常感谢!
21 楼
清风送月
2015-10-19
楼主:为什么我写的时候使用iterator.remove(); 会报java.lang.UnsupportedOperationException
selectionKeys = selector.selectedKeys(); //System.out.println(selectionKeys.size()); iterator = selectionKeys.iterator();
20 楼
zaiyueming
2015-04-02
sj4268778 写道
都跑的通么??端口号都不一致。。
hekuilove 写道
端口不一样你是怎么跑起来的
这种小事何必纠结,自己不会改?
19 楼
hekuilove
2015-03-16
端口不一样你是怎么跑起来的
18 楼
sj4268778
2015-03-02
都跑的通么??端口号都不一致。。
17 楼
kennykinte
2014-06-18
xunke515 写道
-------------
NIOServer 类第101行有些问题
如果继续注册读事件,服务端会持续得进行循环.
这样客户端接受不到服务端返回得数据,会一直保持连接.
---------
应该将NIOServer 类第101行替换为client.close() ;
---------
欢迎拍砖.
兄台说的不太正确哦...
主贴代码就是让C/S两端不断循环读取,发送数据的, 只要客户端向服务端发送数据了,服务端就会回一条消息给客户端,如此反复.
如果将NIOServer 类第101行替换为client.close() ;
那么客户端就被关闭了.
16 楼
kennykinte
2014-06-18
softkf 写道
我也有点纳闷,如果把如下代码
else if (selectionKey.isWritable()) {
//将缓冲区清空以备下次写入
sendbuffer.clear();
// 返回为之创建此键的通道。
client = (SocketChannel) selectionKey.channel();
sendText="message from server--" + flag++;
//向缓冲区中输入数据
sendbuffer.put(sendText.getBytes());
//将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位
sendbuffer.flip();
//输出到通道
client.write(sendbuffer);
System.out.println("服务器端向客户端发送数据--:"+sendText);
client.register(selector, SelectionKey.OP_READ);
}
中的红色部分去掉,就会出现服务器一直往客户端打印东西? 这是为何? 兄台弄清楚了么?
看我上一条回复, register方法会覆盖前一次register方法的效果. 所以如果你这边不加这条红色语句, 那么在这个channel里的事件就一直是OP_WRITE了,所以每次select()都会执行selectionKey.isWritable()这段的逻辑, 就一直给客户端发送数据了.
15 楼
kennykinte
2014-06-18
zk1878 写道
对nio不是很了解,这里有个疑问,在client那的代码
为什么当selectionKey.isConnectable()时,只注册了
SelectionKey.OP_READ,而不注册SelectionKey.OP_WRITE;
还有当selectionKey.isWritable()时,为什么每次都要注册
SelectionKey.OP_READ,我觉得应该是在selectionKey.isConnectable()
时同时注册OP_READ,OP_WRITE吧
为什么当selectionKey.isConnectable()时,只注册了
SelectionKey.OP_READ,而不注册SelectionKey.OP_WRITE;
还有当selectionKey.isWritable()时,为什么每次都要注册
SelectionKey.OP_READ,我觉得应该是在selectionKey.isConnectable()
时同时注册OP_READ,OP_WRITE吧
对于某个指定的socketchannel,调用register方法会覆盖前一次调用register的效果,而你想在selectionKey.isConnectable()这里同时注册OP_READ和OP_WRITE事件的话, 可以这么写client.register(selector, SelectionKey.OP_READ|SelectionKey.OP_WRITE);
但是主贴里selectKey循环遍历的时候, 又用的是if-else结构,所以你注册2个事件,也不会都执行到.
但是按照主贴里的写法,在isConnectable()里注册OP_READ,程序下次就会进入isReadable(),在isReadable()里又注册OP_WRITE, 这样就把OP_READ给覆盖掉了,程序下次就进入isWritable(),在isWritable()又注册了OP_READ,下一次就进入isReadable()....如此反复循环, 所以主贴代码是对的.
当然这种结构好不好, 我就不评论了.
14 楼
kennykinte
2014-06-17
josico 写道
问一下 为什么在遍历迭代器的时候 要做一次remove操作?
我觉得一点意义都没有啊
我觉得一点意义都没有啊
http://www.molotang.com/articles/906.html
这个帖子里有解释为什么要remove
13 楼
josico
2014-06-17
问一下 为什么在遍历迭代器的时候 要做一次remove操作?
我觉得一点意义都没有啊
我觉得一点意义都没有啊
12 楼
xunke515
2014-03-23
softkf 写道
zk1878 写道
对nio不是很了解,这里有个疑问,在client那的代码
为什么当selectionKey.isConnectable()时,只注册了
SelectionKey.OP_READ,而不注册SelectionKey.OP_WRITE;
还有当selectionKey.isWritable()时,为什么每次都要注册
SelectionKey.OP_READ,我觉得应该是在selectionKey.isConnectable()
时同时注册OP_READ,OP_WRITE吧
为什么当selectionKey.isConnectable()时,只注册了
SelectionKey.OP_READ,而不注册SelectionKey.OP_WRITE;
还有当selectionKey.isWritable()时,为什么每次都要注册
SelectionKey.OP_READ,我觉得应该是在selectionKey.isConnectable()
时同时注册OP_READ,OP_WRITE吧
我也有点纳闷,如果把如下代码
else if (selectionKey.isWritable()) {
//将缓冲区清空以备下次写入
sendbuffer.clear();
// 返回为之创建此键的通道。
client = (SocketChannel) selectionKey.channel();
sendText="message from server--" + flag++;
//向缓冲区中输入数据
sendbuffer.put(sendText.getBytes());
//将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位
sendbuffer.flip();
//输出到通道
client.write(sendbuffer);
System.out.println("服务器端向客户端发送数据--:"+sendText);
client.register(selector, SelectionKey.OP_READ);
}
中的红色部分去掉,就会出现服务器一直往客户端打印东西? 这是为何? 兄台弄清楚了么?
-------------
NIOServer 类第101行有些问题
如果继续注册读事件,服务端会持续得进行循环.
这样客户端接受不到服务端返回得数据,会一直保持连接.
---------
应该将NIOServer 类第101行替换为client.close() ;
---------
欢迎拍砖.
11 楼
softkf
2014-02-25
zk1878 写道
对nio不是很了解,这里有个疑问,在client那的代码
为什么当selectionKey.isConnectable()时,只注册了
SelectionKey.OP_READ,而不注册SelectionKey.OP_WRITE;
还有当selectionKey.isWritable()时,为什么每次都要注册
SelectionKey.OP_READ,我觉得应该是在selectionKey.isConnectable()
时同时注册OP_READ,OP_WRITE吧
为什么当selectionKey.isConnectable()时,只注册了
SelectionKey.OP_READ,而不注册SelectionKey.OP_WRITE;
还有当selectionKey.isWritable()时,为什么每次都要注册
SelectionKey.OP_READ,我觉得应该是在selectionKey.isConnectable()
时同时注册OP_READ,OP_WRITE吧
我也有点纳闷,如果把如下代码
else if (selectionKey.isWritable()) {
//将缓冲区清空以备下次写入
sendbuffer.clear();
// 返回为之创建此键的通道。
client = (SocketChannel) selectionKey.channel();
sendText="message from server--" + flag++;
//向缓冲区中输入数据
sendbuffer.put(sendText.getBytes());
//将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位
sendbuffer.flip();
//输出到通道
client.write(sendbuffer);
System.out.println("服务器端向客户端发送数据--:"+sendText);
client.register(selector, SelectionKey.OP_READ);
}
中的红色部分去掉,就会出现服务器一直往客户端打印东西? 这是为何? 兄台弄清楚了么?
10 楼
zk1878
2014-01-14
对nio不是很了解,这里有个疑问,在client那的代码
为什么当selectionKey.isConnectable()时,只注册了
SelectionKey.OP_READ,而不注册SelectionKey.OP_WRITE;
还有当selectionKey.isWritable()时,为什么每次都要注册
SelectionKey.OP_READ,我觉得应该是在selectionKey.isConnectable()
时同时注册OP_READ,OP_WRITE吧
为什么当selectionKey.isConnectable()时,只注册了
SelectionKey.OP_READ,而不注册SelectionKey.OP_WRITE;
还有当selectionKey.isWritable()时,为什么每次都要注册
SelectionKey.OP_READ,我觉得应该是在selectionKey.isConnectable()
时同时注册OP_READ,OP_WRITE吧
9 楼
Jnerd
2014-01-13
运行不了啊,服务端没有接收到字符串,只是连接上了
8 楼
632578551a
2013-03-06
关于 一条读写操作完成之后修改通道关心事件为什么不用
key的interestOps方法???
key的interestOps方法???
7 楼
刚开始吧
2013-02-26
这个程序的目的是什么?弄的我很模糊
6 楼
luisfabiano
2013-01-14
listen 方法是私有方法啊。怎么能随便调用呢?
5 楼
wangxinshui87
2012-11-30
为什么不把服务端和客户端的port写一致呢?
4 楼
lgfy1984
2012-09-26
好文,收藏
3 楼
xm_king
2012-07-06
sahala3293 写道
构造方法里面是不是尽量不要抛出异常,会不会导致一些奇怪的问题
这个也是要根据具体情况和场景分析,比如说,在构造方法中需要建立数据库连接,如果数据库连接异常的话,那最好就抛个异常出来,让上层知道。
发表评论
-
Java动态绑定机制的内幕(转载)
2011-05-19 22:45 2316在Java方法调用的过程中,JVM是如何知道调用的是哪个类的方 ... -
Static和Final的深度理解
2011-05-19 10:57 4134在Java中,static和final是使用频率非 ... -
自己动手写DataSource
2010-11-02 13:09 6342DataSource 对象所表示的物理数据源 ... -
DriverManager和Class.forName()的异同
2010-10-30 12:48 6593在学习JDBC的时候,通常有两种方式去注册数据库驱动程序(这里 ... -
Java的局部内部类以及final类型的参数和变量
2010-09-27 15:52 4747Thinking In Java里 ... -
重载与覆盖区别
2010-09-16 23:40 3773重载与覆盖区别 有时候,类的同一种功能有多种实现方式, ... -
JAVA模拟线程池
2010-09-14 15:28 3125线程池就像数据库连接池一样,是一个对象池。所有的 ... -
HashCode和equals方法深度分析
2010-08-31 22:51 1536在往HashSet集合中放数据的时 ... -
[转]Java编码浅析
2010-08-29 16:09 1634Java与Unicode: Java的cl ... -
java final变量(转)
2010-08-26 14:47 2335final变量定义: 变量一经初始化就不能指向其它 ... -
JAVA中方法和变量在继承中的覆盖和隐藏
2010-08-24 13:07 2051关键字: java继承 方法覆盖 方法隐藏 ... -
java静态方法能否被重写
2010-08-24 11:52 13981JAVA静态方法 ... -
StringBuffer可变String不可变的真正原因
2010-08-23 19:19 2786String和StringBuffer 都是fi ... -
ANT笔记(二)
2010-06-09 09:01 2147四、 生成一个简单的 JA ... -
ANT笔记(一)
2010-06-09 08:59 1462一、 Ant ... -
Java的反射机制和动态代理
2010-06-09 08:29 2005运行时信息(RunT ... -
JNDI和Java RMI远程调用(二)
2010-06-07 21:22 5494利用 JNDI 定位资源 JNDI ... -
JNDI和Java RMI远程调用(一)
2010-06-07 11:32 5104对于 Java EE 开发来说, ... -
Java方法继承、方法重载、方法覆盖小总结
2010-03-17 14:59 1586Java方法继承、方法重载 ...
相关推荐
在这个javaNIO实例中,我们可以学习到如何利用Java NIO进行文件的读取、写入以及复制操作。 首先,NIO的核心组件包括通道(Channels)、缓冲区(Buffers)和选择器(Selectors)。通道是数据传输的路径,如文件通道...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java从1.4版本开始引入的一种新的I/O模型,它为Java应用程序提供了更高效的数据传输方式。传统的Java I/O模型(BIO)在处理大量并发连接时效率较...
Java NIO,全称为Non-Blocking Input/Output(非阻塞输入/输出),是Java从1.4版本开始引入的一种新的I/O模型,它为Java程序员提供了更高效、灵活的I/O操作方式。NIO与传统的 Blocking I/O(阻塞I/O)相比,主要的...
"Java NIO实例UDP发送接收数据代码分享" Java NIO(Non-blocking I/O)是一种异步I/O模型,允许开发者在单个线程中处理多个I/O操作,从而提高程序的性能和可扩展性。在Java NIO中,DatagramChannel是专门用于发送...
标题“nio.rar_NIO_NIO-socket_java nio_java 实例_java.nio”表明这个压缩包包含了一个关于Java NIO的实例,特别是关于NIO套接字(Socket)的编程示例。NIO套接字是Java NIO库中用于网络通信的关键组件,它们允许...
在这个实例中,"java NIO 消息推送实例" 旨在展示如何使用NIO进行服务器向客户端的消息推送。 1. **Java NIO基础** - **通道(Channels)**:Java NIO 提供了多种通道,如文件通道、套接字通道等,它们代表不同...
Java NIO 深入探讨了 1.4 版的 I/O 新特性,并告诉您如何使用这些特性来极大地提升您所写的 Java 代码的执行效率。这本小册子就程序员所面临的有代表性的 I/O 问题作了详尽阐述,并讲解了 如何才能充分利用新的 I/O ...
在标题中提到的“java-nio.rar_java nio_nio 对象实例化”,我们可以理解为这个压缩包中包含了关于Java NIO对象实例化的具体示例或教程。下面我们将详细讨论NIO中的核心对象及其实例化方法。 1. **通道(Channel)*...
本资料"JavaNIO服务器实例Java开发Java经验技巧共6页"可能是某个Java开发者或讲师分享的一份关于如何在Java中构建NIO服务器的教程,涵盖了6个关键页面的内容。尽管具体的细节无法在此直接提供,但我们可以根据Java ...
Java NIO(New IO)是Java 1.4版本引入的一个新API,全称为Non-blocking Input/Output,它提供了一种不同于传统IO的编程模型,传统IO...在实际编码时,参考博文链接中的代码实例,可以帮助你更好地理解和实践Java NIO。
Java NIO(New IO)是Java 1.4版本引入的一个新模块,它提供了一种不同于标准Java IO API的处理I/O操作的方式。NIO的主要特点是面向缓冲区,非阻塞I/O,以及选择器,这些特性使得NIO在处理大量并发连接时表现出更高...
Java NIO(New Input/Output)是Java标准库提供的一种I/O模型,它与传统的 Blocking I/O(BIO)模型不同,NIO提供了非阻塞的读写方式,...对于理解和实践Java NIO在网络编程中的应用,这是一个非常有价值的参考实例。
总之,这个Java NIO IM实例是一个很好的学习资源,它演示了如何利用NIO进行高效的网络通信。通过深入理解并实践这个示例,开发者可以更好地掌握Java NIO的核心概念和技术,并将其应用于实际项目中,提升系统的性能和...
Java NIO(New IO)是Java 1.4版本引入的一个新模块,全称为Non-blocking Input/Output,它提供了一种不同于传统IO的编程模型,传统IO基于块I/O(Blocking I/O),而NIO则基于通道(Channels)和缓冲区(Buffers)...
**JAVA-NIO程序设计完整实例** Java NIO(New IO)是Java 1.4引入的一个新特性,它为Java提供了非阻塞I/O操作的能力,使得Java在处理I/O时更加高效。NIO与传统的BIO(Blocking I/O)模型相比,其核心在于它允许程序...
Java NIO(New Input/Output)是Java标准库中提供的一种I/O模型,与传统的BIO( Blocking I/O)相比,NIO...对于初学者来说,这些源码实例可以帮助理解Java NIO的基本用法和优势,进一步提升在实际项目中的应用能力。
Java NIO(New IO)是Java 1.4引入的一个新特性,它是对传统IO模型的重大改进,提供了更高效的数据处理方式。NIO的核心概念包括通道(Channels)、缓冲区(Buffers)和选择器(Selectors)。它允许多个输入/输出操作...
### Java NIO原理 图文分析及代码实现 #### 前言 在深入探讨Java NIO之前,我们先简要回顾一下NIO的概念及其引入的原因。随着互联网的发展,越来越多的应用程序需要处理高并发的网络连接请求。传统的阻塞I/O模型在...
四、NIO应用实例 1. **文件操作**:使用FileChannel进行文件的读写,例如将一个文件复制到另一个文件。 2. **网络通信**:使用SocketChannel和ServerSocketChannel进行客户端和服务器端的连接与数据传输。 3. **多...