首页 诗词 字典 板报 句子 名言 友答 励志 学校 网站地图
当前位置: 首页 > 教程频道 > 开发语言 > 编程 >

java nio进程

2012-12-22 
java nio过程1、服务端:ServerSocketChannel进行监听,注册SelectionKey.OP_ACCEPT事件,服务器阻塞在selecto

java nio过程

1、服务端:ServerSocketChannel进行监听,注册SelectionKey.OP_ACCEPT事件,服务器阻塞在selector.select()方法中,等待客户端连接。
2、客户端:SocketChannel创建连接,调用socketChannel.connect(SERVER_ADDRESS)连接服务器(此时服务器之前阻塞在selector.select()往下走,进入selectionKey.isAcceptable()逻辑,通过ServerSocketChannel的accept方法获得客户端SocketChannel,SocketChannel注册 SelectionKey.OP_READ事件,等待客户端输入流,此时又阻塞在selector.select()方法),客户端进入selectionKey.isConnectable(),如果client.isConnectionPending()==true,通过 client.finishConnect()强制连接,然后准备数据,通过client.write(sendbuffer)向服务器发送数据,此时,服务器之前阻塞在selector.select()往下走,进入selectionKey.isReadable()逻辑,通过缓冲区读取客户端输入流,然后调用client.register(selector, SelectionKey.OP_WRITE)注册写客户端流事件,进入selectionKey.isWritable()逻辑,准备写客户端的数据,通过client.write(sendbuffer)方法写给客户端,客户端之前write之后,会进行注册SelectionKey.OP_READ,等待服务器响应,阻塞在selector.select()中,由于这个时候服务器有了返回,就不阻塞了,进入selectionKey.isReadable()逻辑,得到服务器返回,如果需要再次发送数据给服务器,则注册write事件。刚才服务器write给客户端之后,如果想继续收到客户端数据,需要注册client.register(selector, SelectionKey.OP_READ)读事件,等待客户端再一次写入数据,阻塞在selector.select()方法

?

服务端:

package com.rb.socket.nio.server.n;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----:" + port);}// 监听   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 = 8011;NIOServer server = new NIOServer(port);server.listen();}}

?

客户端:

package com.rb.socket.nio.server.n;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", 8011);         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();           }       }   }  

?

?

热点排行