天天看點

JAVA NIO 執行個體_亮仔_新浪部落格

http://xm-king.iteye.com/blog/766330最近一直在忙着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 selectionKeys = selector.selectedKeys();

   Iterator 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);

  }

 }

 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 selectionKeys;

  Iterator 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();

  }

 }

}