IO NIO 区别请看 : http://blog.****.net/jiangtao_st/article/details/38041479
一、基于Nio的 Server ,过程略复杂,但是无疑这样的效率高;代码中得注释比较详细,请看注释说明
package com.zhuoxuan.net.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.Random; import java.util.Set; /** * * <p> * 基于nio的Server * </p> * * @author 卓轩 * @创建时间:2014年7月7日 * @version: V1.0 */ public class NioServer { private final int port = 8787; private final int BLOCK_SIZE = 4096; private Selector selector; private ByteBuffer receiveBuffer = ByteBuffer.allocate(BLOCK_SIZE); private ByteBuffer sendBuffer = ByteBuffer.allocate(BLOCK_SIZE); //构造函数 public NioServer() throws IOException { //打开服务器套接字通道 ServerSocketChannel serverSocketChannel = ServerSocketChannel.open(); //服务器配置为非阻塞模式 serverSocketChannel.configureBlocking(false); //获取与通道关联的 ServerSocket对象 ServerSocket serverSocket = serverSocketChannel.socket(); //绑定端口 serverSocket.bind(new InetSocketAddress(port)); //打开一个选择器 selector = Selector.open(); //注册到selector上,等待连接 serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT); System.out.println("Server:init successfuly."); } /** * 监听端口 */ private void linstenr() throws Exception{ while (true) { //选择一组键 selector.select(); //返回获取选择的键集 Set<SelectionKey> selectionKeys = selector.selectedKeys(); if(selectionKeys.isEmpty()){ continue; } //遍历,循环处理请求的键集 Iterator<SelectionKey> iterator = selectionKeys.iterator(); while (iterator.hasNext()) { SelectionKey selectionKey = (SelectionKey) iterator.next(); iterator.remove(); handlerKey(selectionKey); } Thread.sleep(4000); } } /** * 处理对应的 SelectionKey * @param selectionKey */ private void handlerKey(SelectionKey selectionKey) throws IOException{ ServerSocketChannel server; SocketChannel client; // 测试此键的通道是否已准备好接受新的套接字连接 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(); //将客户端发送来的数据读取到 buffer中 int count = client.read(receiveBuffer); if(count >0){ String receiveMessage = new String(receiveBuffer.array(),0,count); System.out.println("Server:接受客户端的数据:" + receiveMessage); client.register(selector, SelectionKey.OP_WRITE); } } else if (selectionKey.isWritable()) { //发送消息buffer 清空 sendBuffer.clear(); //返回该键对应的通道 client = (SocketChannel)selectionKey.channel(); String sendMessage = "Send form Server...Hello... "+new Random().nextInt(100)+" ."; //向缓冲区中写入数据 sendBuffer.put(sendMessage.getBytes()); //put了数据,标志位被改变 sendBuffer.flip(); //数据输出到通道 client.write(sendBuffer); System.out.println("Server:服务器向客户端发送数据:" + sendMessage); client.register(selector, SelectionKey.OP_READ); } } public static void main(String[] args) { try { NioServer nioServer = new NioServer(); nioServer.linstenr(); } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }
package com.zhuoxuan.net.nio; 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; /** * * <p> * nio client * </p> * * @author 卓轩 * @创建时间:2014年7月7日 * @version: V1.0 */ public class NioClient { private static final int BLOCK_SIZE = 4096; private static ByteBuffer sendBuffer = ByteBuffer.allocate(BLOCK_SIZE); private static ByteBuffer receiveBuffer = ByteBuffer.allocate(BLOCK_SIZE); private static final InetSocketAddress SERVER_ADDRESS = new InetSocketAddress("127.0.0.1",8787); public static void main(String[] args) { try { //打开socket通道 SocketChannel socketChannel = SocketChannel.open(); //设置为非阻塞模式 socketChannel.configureBlocking(false); //打开选择器 Selector selector = Selector.open(); //向selector 选择器注册此通道 socketChannel.register(selector, SelectionKey.OP_CONNECT); //链接 socketChannel.connect(SERVER_ADDRESS); SocketChannel client; while (true) { //选择一组键 selector.select(); //返回此选择器的已选择键集 Set<SelectionKey> selectionKeys = selector.selectedKeys(); Iterator<SelectionKey> iterator = selectionKeys.iterator(); //遍历对应的 SelectionKey 处理 while (iterator.hasNext()) { SelectionKey selectionKey = (SelectionKey) iterator.next(); //判断此键的通道是否已完成其套接字连接操作 if (selectionKey.isConnectable()) { System.out.println("Client: already connected."); client = (SocketChannel)selectionKey.channel(); //判断该通道是否进行连接过程、完成连接过程 if(client.isConnectionPending()){ client.finishConnect(); sendBuffer.clear(); sendBuffer.put("hello nio server".getBytes()); sendBuffer.flip(); client.write(sendBuffer); //将数据写入该通道 client.register(selector, SelectionKey.OP_READ); } } else if(selectionKey.isReadable()){ //获取该键中对应的通道 client = (SocketChannel)selectionKey.channel(); receiveBuffer.clear(); int count = client.read(receiveBuffer); if(count > 0){ String receiveMessage = new String(receiveBuffer.array(),0,count); System.out.println("Client:接收到来自Server的消息," + receiveMessage); client.register(selector, SelectionKey.OP_WRITE); } } else if(selectionKey.isWritable()){ sendBuffer.clear(); client = (SocketChannel) selectionKey.channel(); String sendText = "hello server,key.."; sendBuffer.put(sendText.getBytes()); //将缓冲区各标志复位,因为向里面put了数据标志被改变要想从中读取数据发向服务器,就要复位 sendBuffer.flip(); client.write(sendBuffer); System.out.println("Client:客户端向服务器端发送数据--:"+sendText); client.register(selector, SelectionKey.OP_READ); } } selectionKeys.clear(); Thread.sleep(3000); } } catch (Exception e) { // TODO Auto-generated catch block e.printStackTrace(); } } }