基于java底层api实现的nio
2017-04-07 00:00
393 查看
摘要: ServerSocketChannel SocketChannel 笔记
服务器端
客户端
服务器端
package nio; 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.ServerSocketChannel; import java.nio.channels.SocketChannel; import java.util.Iterator; import java.util.Map; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public class Server { private static ByteBuffer recvBuf = ByteBuffer.allocate(1024); private static ByteBuffer respBuf = ByteBuffer.allocate(1024); private static Map<SelectionKey,Object> sessionMessage = new ConcurrentHashMap<SelectionKey,Object>(); public static void main(String[] args) throws IOException { //多路复用器 Selector selector = Selector.open(); //创建server ServerSocketChannel server = ServerSocketChannel.open(); server.socket().bind(new InetSocketAddress(9999));//绑定端口 server.configureBlocking(false);//设置非阻塞 //server上注册一个多路复用器 事件标签OP_ACCEPT接收客户端连接 这样多路复用器将不断轮询server,当有客户端连接过来,就会被轮询出来 server.register(selector, SelectionKey.OP_ACCEPT); System.out.println("服务器已经启动"); //启动监听 listener(server, selector); } public static void listener(ServerSocketChannel server, Selector selector ) throws IOException{ while (true) { int eventCount = selector.select();//如果有客户端连接过来,就会被轮询出来 if (eventCount <= 0) {//小于等于0,说明没有客户端接入 continue; } Set<SelectionKey> keys = selector.selectedKeys();//获取有事件触发的selectkey Iterator<SelectionKey> iter = keys.iterator(); while (iter.hasNext()) { SelectionKey key = iter.next(); //处理事件 try { process(server,selector,key); } catch (IOException e) {//客户端异常关闭 close(key); } iter.remove();//处理完移除这个事件 } } } public static void process(ServerSocketChannel server, Selector selector ,SelectionKey key) throws IOException{ SocketChannel client = null; if (key.isValid() && key.isAcceptable() ) {//事件是否是有效的 client = server.accept();//有客户端接入,把客户端连接通道也注册到多路复用器上 client.configureBlocking(false);//非阻塞的 client.register(selector, SelectionKey.OP_READ);//客户端连接过来,注册读事件 }else if(key.isValid() && key.isReadable()){//可读的,说明注册在多路复用上的客户端有数据发过来了 recvBuf.clear();//清空缓冲区 client = (SocketChannel) key.channel();//通过key获取到客户端,这个客户端是在Acceptable时连接过来的客户端 int length = client.read(recvBuf);//将数据读到缓冲区 if (length > 0) {//读取到内容的时候 String message = new String(recvBuf.array(),0,length); sessionMessage.put(key, message);//将数据放到sessionmessage中 key.interestOps(SelectionKey.OP_WRITE);//读完数据后,这个客户端在多路复用器上的事件由read变为write,可以写了 }else{ if (client.isConnected()) { System.out.println("客户端关闭"); close(key); } } }else if(key.isValid() && key.isWritable()){//可写的,说明注册在多路复用上的客户端数据已经接收完了,可以往客户端写数据了 if (!sessionMessage.containsKey(key)) { return; } //获取到客户端发送过来的数据 client = (SocketChannel) key.channel(); Object resp = handler(sessionMessage.get(key));//将读取到的数据暴露给用户处理,得到响应数据 respBuf.clear(); respBuf.put((ByteBuffer)resp); respBuf.flip(); client.write(respBuf);//响应客户端 key.interestOps(SelectionKey.OP_READ);//写完数据后,这个客户端在多路复用器上的事件又由write变为read,可以读了 }else{ client = server.accept();//有客户端接入,把客户端连接通道也注册到多路复用器上 System.out.println("连接状态::"+client.isConnected()); } } public static ByteBuffer handler(Object message){ System.out.println("来自客户端的消息:"+message); return ByteBuffer.wrap((message+"这是响应").getBytes()); } public static void close(SelectionKey key){ key.cancel();//取消注册 SocketChannel client = (SocketChannel) key.channel(); try { if (client != null) { client.socket().close(); } } catch (IOException e) { e.printStackTrace(); } } }
客户端
package nio; 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.Map; import java.util.Scanner; import java.util.Set; import java.util.concurrent.ConcurrentHashMap; public class Client { private static ByteBuffer sendBuf = ByteBuffer.allocate(1024); private static ByteBuffer respBuf = ByteBuffer.allocate(1024); private static Map<SelectionKey,Object> sessionMessage = new ConcurrentHashMap<SelectionKey,Object>(); public static void main(String[] args) throws IOException { //多路复用器 Selector selector = Selector.open(); //客户端 SocketChannel client = SocketChannel.open(); client.configureBlocking(false); client.register(selector, SelectionKey.OP_CONNECT);//注册连接事件 client.connect(new InetSocketAddress("localhost", 9999));//连接服务器,触发connect事件 //监听客户端事件 listener(client,selector); } private static void listener(SocketChannel client, Selector selector) throws IOException { while (true) { int eventCount = selector.select();//如果有客户端连接过来,就会被轮询出来 if (eventCount <= 0) {//小于等于0,说明没有事件触发 continue; } Set<SelectionKey> keys = selector.selectedKeys();//获取有事件触发的selectkey Iterator<SelectionKey> iter = keys.iterator(); while (iter.hasNext()) { SelectionKey key = iter.next(); //处理事件 try { process(client,selector,key); } catch (IOException e) {//客户端异常关闭 //close(key); } iter.remove();//处理完移除这个事件 } } } private static void process(SocketChannel client, Selector selector, SelectionKey key) throws IOException{ Scanner scan = new Scanner(System.in); SocketChannel channel = null; if (key.isValid() && key.isConnectable() ) {//事件是否是有效的 channel = (SocketChannel) key.channel(); if (channel.isConnectionPending()) {//如果正在连接,完成连接 channel.configureBlocking(false); channel.finishConnect(); System.out.println("客户端连接成功"); } client.register(selector, SelectionKey.OP_WRITE);//客户端连接上了,可以写了 }else if(key.isValid() && key.isWritable()){//可写了,向服务器端发送消息 System.out.println("可以写了-----"); String line = scan.next(); if (line.equals("finsh")) { System.out.println("关闭了..."); key.cancel(); client.close(); System.exit(1); }else{ sendBuf.clear(); sendBuf.put(line.getBytes()); sendBuf.flip(); client.write(sendBuf);//响应客户端 key.interestOps(SelectionKey.OP_READ);//写完数据后,这个客户端在多路复用器上的事件又由write变为read,可以读了 } }else if(key.isValid() && key.isReadable()){//可读,获取服务器端响应 System.out.println("可以读了-----"); respBuf.clear();//清空缓冲区 int length = client.read(respBuf);//将数据读到缓冲区 if (length > 0) {//读取到内容的时候 String message = new String(respBuf.array(),0,length); System.out.println("client-响应信息::::"+message); key.interestOps(SelectionKey.OP_WRITE);//读完数据后,这个客户端在多路复用器上的事件由read变为write,可以写了 } } } }
相关文章推荐
- 基于java的zabbix api调用实现数据共享
- Java——基于java自身包实现消息系统间的通信(TCP/IP+NIO)
- 基于TCP/UDP的NIO服务端/客户端代码实现damo(java)
- 基于 java nio 长连接实现的聊天室
- [分布式java]基于JavaAPI实现消息方式的系统间通信:TCP/IP+NIO
- 基于java的nio消息实现方式优缺点分析及示例代码说明
- 基于 Java NIO 实现简单的 HTTP 服务器
- ES Java API_基于scroll实现月度销售数据批量下载
- java分布式开发TCP/IP NIO无阻塞 Socket((基于消息方式实现系统间的通信) )(转)
- java底层代码分析:Java NIO原理图文分析及代码实现
- Java动态代理详解,以及底层JDK源码实现分析(基于Java8)。
- Netty学习之旅------线程模型前置篇Reactor反应堆设计模式实现(基于java.nio)
- ES Java API_基于search template实现按品牌分页查询模板
- [分布式java]基于JavaAPI实现消息方式的系统间通信:UDP/IP+NIO
- Zabbix实践(五):基于java的zabbix api调用实现数据共享
- 利用JNI实现java的串口通讯技术(基于C++的底层)
- Java——基于java自身包实现消息系统间的通信(TCP/IP+NIO)
- 基于MTD的NANDFLASH设备驱动底层实现原理分析(一)
- 数据挖掘-基于贝叶斯算法及KNN算法的newsgroup18828文本分类器的JAVA实现(上)
- 基于JAVA的SIP代理PEERS的自动放音实现