本文主要通过一个非常简单的Server实例总结一下基于Java非阻塞IO的网络编程。
希望对大家有所帮助,欢迎拍砖!
一、Server端代码:
该示例主要实现一个简单功能,server端直接打印客户端发送的数据。
由于例子非常简单,一个线程循环处理所有任务,算是一个最简单的NIO Server吧(实际应用开发中是不会采用这种方式的)。
MyNIOServer.java:
public class MyNIOServer { private static final int TIMEOUT = 30000; private static final int BUFSIZE = 10; private Selector selector; public MyNIOServer(int port) throws Exception{ System.out.println("server start on port:"+port); ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); serverSocketChannel.configureBlocking(false); ServerSocket serverSocket = serverSocketChannel.socket(); serverSocket.bind(new InetSocketAddress(port)); selector = Selector.open(); serverSocketChannel.register(selector,SelectionKey.OP_ACCEPT); } public void listen() throws Exception{ System.out.println("server listen!"); MyNIOServerHandler handler = new MyNIOServerHandler(BUFSIZE); while(true){ System.out.println("listen while!"); if (selector.select(TIMEOUT) == 0) { System.out.print("."); continue; } Iterator<SelectionKey> keyIter = selector.selectedKeys().iterator(); while(keyIter.hasNext()){ SelectionKey key = keyIter.next(); if(key.isAcceptable()){ System.out.println("isAcceptable!"); handler.handleAccept(key); }else if(key.isReadable()){ System.out.println("isReadable!"); handler.handleRead(key); }else if(key.isValid() && key.isWritable()){ System.out.println("isWritable!"); handler.handleWrite(key); } keyIter.remove(); } } } public static void main(String[] args){ try{ MyNIOServer server=new MyNIOServer(9009); server.listen(); }catch(Exception e){ e.printStackTrace(); } } }
处理器MyNIOServerHandler.java:
public class MyNIOServerHandler { private int BUFSIZE; public MyNIOServerHandler(int bufferSize){ this.BUFSIZE = bufferSize; } public void handleAccept(SelectionKey key) throws IOException{ System.out.println("handleAccept..."); ServerSocketChannel serverChannel = (ServerSocketChannel)key.channel(); SocketChannel clientChannel = serverChannel.accept(); clientChannel.configureBlocking(false); Selector selector = key.selector(); clientChannel.register(selector, SelectionKey.OP_READ,ByteBuffer.allocate(BUFSIZE)); } public void handleRead(SelectionKey key) throws IOException{ System.out.println("handleRead..."); SocketChannel clientChannel = (SocketChannel)key.channel(); ByteBuffer buf = (ByteBuffer) key.attachment(); long bytesRead = clientChannel.read(buf); System.out.println("bytesRead:"+bytesRead); if(bytesRead==-1){ System.out.println("clientChannel close!"); clientChannel.close(); }else if (bytesRead > 0) { String receiveText = new String(buf.array(),0,new Long(bytesRead).intValue()); System.out.println("服务器端接受客户端数据--:"+receiveText); key.interestOps( SelectionKey.OP_WRITE); } } public void handleWrite(SelectionKey key) throws IOException{ System.out.println("handleWrite..."); ByteBuffer buf = (ByteBuffer) key.attachment(); buf.flip(); SocketChannel clntChan = (SocketChannel) key.channel(); clntChan.write(buf); if (!buf.hasRemaining()) { key.interestOps(SelectionKey.OP_READ); } buf.compact(); } }
代码注解:
服务器端创建一个选择器,将其与每个侦听客户端连接的套接字所对应的ServerSocketChannel注册在一起,然后反复循环,调用select()方法,并调用相应的操作器对各种类型的IO操作进行处理。
1、创建一个Selector选择器。
2、创建ServerSocketChannel实例,获得底层的ServerSocket,并以端口号作为参数绑定bind()。
3、设置信道为非阻塞模式,只有非阻塞信道才可以注册选择器。
4、为信道注册选择器,指出该信道可以进行accept操作。
5、反复轮询,等待IO,select()方法将阻塞等待,直到有准备好IO操作的信道,或者直到超时。
6、调用selectedKeys()方法,返回一个Set实例,并从中获取一个Iterator。该集合中包含了每个准备好某一IO操作的信道的SelectionKey(注册时创建)。
7、对于每个键,检查是否准备好accept()操作,是否可读或可写。
8、select()操作只是向selector所关联的键集合中添加元素。因此,不移除处理过的键,下次调用select时仍保留在集合中。
9、channel方法返回注册时用来创建键的channel,即ServerSocketChannel,这是我们注册的唯一一种支持accept操作的信道。accept为传入的连接返回一个SocketChannel实例。
10、可以通过SelectionKey方法获取相应的Selector,当SocketChannel信道准备好读数据的IO操作时,可以通过选出的键集对其进行访问。
12、handleRead,根据其支持数据读取操作可知,这是一个SocketChannel。
13、如果read方法返回-1,则表示底层连接已经关闭,此时需要关闭信道。关闭信道时,将从选择器的各种集合中移除与该信道关联的键。读取完数据将信道标记为可写。
14、handleWrite,如果缓冲区之前接收的数据已经没有剩余,则修改键关联的操作集,指示其只能进行读操作。
二、Client端代码:
MyNIOClient.java
String server = "localhost"; byte[] datas = "1234567890abcdef".getBytes(); int servPort = 9009; SocketChannel clntChan = SocketChannel.open(); clntChan.configureBlocking(false); if (!clntChan.connect(new InetSocketAddress(server, servPort))){ while (!clntChan.finishConnect()){ System.out.print("."); } } ByteBuffer writeBuf = ByteBuffer.wrap(datas); ByteBuffer readBuf = ByteBuffer.allocate(datas.length); int totalBytesRcvd = 0; int bytesRcvd; while(totalBytesRcvd < datas.length){ if(writeBuf.hasRemaining()){ clntChan.write(writeBuf); } if ((bytesRcvd = clntChan.read(readBuf)) == -1){ throw new SocketException("Connection closed prematurely"); } totalBytesRcvd += bytesRcvd; System.out.print("."); } System.out.println("Received:"+new String(readBuf.array(),0,totalBytesRcvd)); clntChan.close();
代码注解:
1、该套接字是非阻塞式的,因此对connect方法的调用可能会在连接建立之前返回。如果在返回前已经成功建立了连接,返回true,否则返回false。返回false时,任何发送或接受数据都将抛出异常。因此通过调用finishConnect方法轮询连接状态。不过这种忙等非常浪费系统资源,此处只是举例。
2、分别采用包装byte数组和allocate方法创建要用来读写数据的bytebuffer实例。
3、反复循环直到发送和接收完所有字节,只要输出缓冲区还留有数据,就调动write方法,对read方法的调用不会阻塞等待,但当没有数据可读时返回0.
4、打印接收到的数据,然后在信道完成其任务后也需要关闭。
相关推荐
Ioserver java Nio socket 框架 是个不错的NIO 通讯框架,本来想学习mina框架,看了看mina的源码太头痛,本人觉得看懂了Ioserver 再看mina的框架,想多的学习 java NIO 的也可以下载 看看,很值得学习啊!!!
Java NIO系列教程(一) Java NIO 概述 Java NIO系列教程(二) Channel Java NIO系列教程(三) Buffer Java NIO系列教程(四) Scatter/Gather Java NIO系列教程(五) 通道之间的数据传输 Java NIO系列教程(六)...
Java NIO(New IO)是一个可以替代标准Java IO API的IO API(从Java 1.4开始),Java NIO提供了与标准IO不同的IO工作方式。 Java NIO: Channels and Buffers(通道和缓冲区) 标准的IO基于字节流和字符流进行操作的,...
NioServer.java
java基于nio的通信实例,带UML结构图及server、client源码。
java NIO是 java New IO 的简称,在 jdk1.4 里提供的新 api 。 Sun 官方标榜的特性如下: – 为所有的原始类型提供 (Buffer) 缓存支持。 – 字符集编码解码解决方案。 – Channel :一个新的原始 I/O 抽象。 – 支持...
java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java NIO和java并发编程的书籍java...
SimpleSocketServer Java IO | NIO样本使用Java IO和NIO设置自己的Socket Server(待办事项) 深入了解Tomcat和Jetty的实现方式(希望如此)
java频道\java io 与java nio区别.txt
JavaNIO服务器实例Java开发Java经验技巧共6页.pdf.zip
1、Java IO_NIO 2、Java+IO.pdf
java NIO 消息推送实例代码,解压Tmp.zip Desk为桌面程序,DeskAppServer为服务端程序,江巅
讲解了 JavaIO 与 JAVA NIO区别,JAVA NIO设计理念,以及JDK中java NIO中语法的使用
该资源包含了一个用javaNIO实现的读写文件以及复制文件的简单的demo,程序注释清晰,简单易懂,喜欢的下载!!!
实例介绍了一个简单的nio实例,适合刚接触nio的童鞋们....
Java NIO系列教程(一) Java NIO 概述
Java IO NIO and NIO 2 英文无水印pdf pdf所有页面使用FoxitReader和PDF-XChangeViewer测试都可以打开 本资源转载自网络,如有侵权,请联系上传者或csdn删除 本资源转载自网络,如有侵权,请联系上传者或csdn...
nio代码实例,Java NIO 系列教程,买不了吃亏,买不了上当
一个java NIO的例子 有很详细的每一步的描述,很好去理解
Java NIO 深入探讨了 1.4 版的 I/O 新特性,并告诉您如何使用这些特性来极大地提升您所写的 Java 代码的执行效率。这本小册子就程序员所面临的有代表性的 I/O 问题作了详尽阐述,并讲解了 如何才能充分利用新的 I/O ...