<rt id="bn8ez"></rt>
<label id="bn8ez"></label>

  • <span id="bn8ez"></span>

    <label id="bn8ez"><meter id="bn8ez"></meter></label>

    posts - 1,  comments - 25,  trackbacks - 0

    java nio小結

    根據網上的資料做些整理

    Java NIO API詳解

    http://www.tkk7.com/19851985lili/articles/93524.html

    這篇文章對nio的api講解比較全,可以幫助在宏觀上把握nio。

    BIO 方式使得整個處理過程和連接是綁定的,只要連接建立,無論客戶端是否有消息發送,都要進行等待處理,一定程度上浪費了服務器端的硬件資源,因此就有了NIO 方式。Java 對于 NIO 方式的支持是通過 Channel和 Selector 方式來實現,采用的方法為向 Channel注冊感興趣的事件,然后通過 Selector 來獲取到發生了事件的 key,如發生了相應的事件,則進行相應的處理,否則則不做任何處理,是典型的Reactor 模式,按照這樣的方式,就不用像 BIO 方式一樣,即使在沒有消息的情況下也需要占據一個線程來阻塞讀取消息,從而提升服務器的使用效率, 為實現 TCP/IP+NIO 方式的系統間通訊, Java 提供了 SocketChannel和 ServerSocketChannel兩個關鍵的類,網絡 IO 的操作則改為通過ByteBuffer 來實現,具體的基于 java實現TCP/IP+NIO 方式的通訊的方法如下所示。

    服務器端:

    復制代碼
    package com.eric.test.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.util.Iterator;
    import java.util.Set;
    import java.nio.channels.SocketChannel;

    public class NIOServer {
    /*標志數字*/
    private static int flag = 0;
    /*定義緩沖區大小*/
    private static int block = 4096;
    /*接收緩沖區*/
    private static ByteBuffer receiveBuffer = ByteBuffer.allocate(block);
    /*發送緩沖區*/
    private static ByteBuffer sendBuffer = ByteBuffer.allocate(block);
    /*定義Selector*/
    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:");
    }
    //監聽
    public void listen() throws IOException{

    while(true){
    //監控所有注冊的 channel ,當其中有注冊的 IO 操作可以進行時,該函數返回,并將對應的 SelectionKey 加入 selected-key set
    selector.select();

    //Selected-key set 代表了所有通過 select() 方法監測到可以進行 IO 操作的 channel ,這個集合可以通過 selectedKeys() 拿到
    Set<SelectionKey> selectionKeys = selector.selectedKeys();

    Iterator<SelectionKey> iterator = selectionKeys.iterator();
    while(iterator.hasNext()){
    SelectionKey selectionKey = iterator.next();
    handleKey(selectionKey);
    iterator.remove();
    }
    }

    }
    //處理請求
    public void handleKey(SelectionKey selectionKey) throws IOException{

    //接受請求
    ServerSocketChannel serverSocketChannel = null;

    SocketChannel socketChannel = null;
    String receiveText;
    String sendText;
    int count;
    //測試此鍵的通道是否準備好接受新的套接字連接
    if(selectionKey.isAcceptable()){

    //返回創建此鍵的通道
    serverSocketChannel = (ServerSocketChannel)selectionKey.channel();

    //接受客戶端建立連接的請求,并返回 SocketChannel 對象
    socketChannel = serverSocketChannel.accept();

    //配置為非阻塞
    socketChannel.configureBlocking(false);

    //注冊到selector
    socketChannel.register(selector, SelectionKey.OP_READ);

    }else if(selectionKey.isReadable()){
    //返回為之創建此鍵的通道
    socketChannel = (SocketChannel)selectionKey.channel();

    //將緩沖區清空,以備下次讀取
    receiveBuffer.clear();

    //將發送來的數據讀取到緩沖區

    count = socketChannel.read(receiveBuffer);


    if(count>0){
    receiveText = new String(receiveBuffer.array(),0,count);
    System.out.println("服務器端接受到的數據---"+receiveText);
    socketChannel.register(selector, SelectionKey.OP_WRITE);
    }
    }else if (selectionKey.isWritable()) {
    //將緩沖區清空以備下次寫入
    sendBuffer.clear();

    // 返回為之創建此鍵的通道。
    socketChannel = (SocketChannel) selectionKey.channel();

    sendText="message from server--" + flag++;
    //向緩沖區中輸入數據
    sendBuffer.put(sendText.getBytes());

    //將緩沖區各標志復位,因為向里面put了數據標志被改變要想從中讀取數據發向服務器,就要復位
    sendBuffer.flip();

    //輸出到通道
    socketChannel.write(sendBuffer);

    System.out.println("服務器端向客戶端發送數據--:"+sendText);
    socketChannel.register(selector, SelectionKey.OP_READ);
    }

    }
    public static void main(String[] args) throws IOException {
    int port = 8888;
    NIOServer server = new NIOServer(port);
    server.listen();
    }

    }
    復制代碼

    客戶端

    復制代碼
    package com.eric.test.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.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", 8888);

    public static void main(String[] args) throws IOException {
    // 打開socket通道
    SocketChannel clientChannel = SocketChannel.open();

    // 設置為非阻塞方式
    clientChannel.configureBlocking(false);

    // 打開選擇器
    Selector selector = Selector.open();

    // 注冊連接服務端socket動作
    clientChannel.register(selector, SelectionKey.OP_CONNECT);

    // 連接
    clientChannel.connect(SERVER_ADDRESS);


    SocketChannel socketChannel;
    Set<SelectionKey> selectionKeys;
    String receiveText;
    String sendText;
    int count=0;

    while (true) {
    //選擇一組鍵,其相應的通道已為 I/O 操作準備就緒。
    //監控所有注冊的 channel ,當其中有注冊的 IO 操作可以進行時,該函數返回,并將對應的 SelectionKey 加入 selected-key set
    selector.select();

    //返回此選擇器的已選擇鍵集。
    selectionKeys = selector.selectedKeys();

    //System.out.println(selectionKeys.size());
    for(SelectionKey selectionKey:selectionKeys){

    //判斷是否為建立連接的事件
    if (selectionKey.isConnectable()) {

    System.out.println("client connect");
    socketChannel = (SocketChannel) selectionKey.channel(); //
    // 判斷此通道上是否正在進行連接操作。
    // 完成套接字通道的連接過程。
    if (socketChannel.isConnectionPending()) {

    //完成連接的建立(TCP三次握手)
    socketChannel.finishConnect();

    System.out.println("完成連接!");
    sendBuffer.clear();
    sendBuffer.put("Hello,Server".getBytes());
    sendBuffer.flip();
    socketChannel.write(sendBuffer);
    }
    socketChannel.register(selector, SelectionKey.OP_READ);
    } else if (selectionKey.isReadable()) {
    socketChannel = (SocketChannel) selectionKey.channel();
    //將緩沖區清空以備下次讀取
    receiveBuffer.clear();

    //讀取服務器發送來的數據到緩沖區中
    count=socketChannel.read(receiveBuffer);

    if(count>0){
    receiveText = new String( receiveBuffer.array(),0,count);
    System.out.println("客戶端接受服務器端數據--:"+receiveText);
    socketChannel.register(selector, SelectionKey.OP_WRITE);
    }

    } else if (selectionKey.isWritable()) {
    sendBuffer.clear();
    socketChannel = (SocketChannel) selectionKey.channel();
    sendText = "message from client--" + (flag++);
    sendBuffer.put(sendText.getBytes());
    //將緩沖區各標志復位,因為向里面put了數據標志被改變要想從中讀取數據發向服務器,就要復位
    sendBuffer.flip();

    socketChannel.write(sendBuffer);
    System.out.println("客戶端向服務器端發送數據--:"+sendText);
    socketChannel.register(selector, SelectionKey.OP_READ);
    }
    }
    selectionKeys.clear();
    }
    }
    }
    復制代碼

    小結:之前對Selector注冊事件和SocketChannel有點小困惑。SocketChannel就像一根水管,當監聽到寫事件時,就往管道寫數據;當監聽到讀事件時,就從管道讀出數據。

    posted on 2012-04-25 15:34 Daniel 閱讀(442) 評論(1)  編輯  收藏 所屬分類: CoreJava

    FeedBack:
    # re: java nio小結[未登錄]
    2012-08-27 17:45 | 小李子
    非常感謝,看了好多別人的文章 都好難理解,
    把你的從頭到尾過了一遍,基本的原理已經清楚了.謝謝  回復  更多評論
      
    <2025年5月>
    27282930123
    45678910
    11121314151617
    18192021222324
    25262728293031
    1234567

    常用鏈接

    留言簿(3)

    隨筆檔案

    文章分類

    文章檔案

    相冊

    搜索

    •  

    最新評論

    主站蜘蛛池模板: 免费视频成人国产精品网站| 免费无遮挡无码视频网站| 最近的中文字幕大全免费8| 成年女人色毛片免费看| 亚洲精品亚洲人成在线观看| 亚洲精品福利你懂| 性色av无码免费一区二区三区| 亚洲中文字幕伊人久久无码| 亚洲av无码一区二区三区天堂古代| 男女猛烈无遮掩视频免费软件| 91成人在线免费视频| 亚洲人成无码网WWW| 亚洲美国产亚洲AV| 免费A级毛片无码久久版| 中文字幕亚洲第一在线| 一级做受视频免费是看美女 | 中文字幕在线观看亚洲| 黄色一级视频免费| 精品亚洲一区二区三区在线观看 | 免费观看国产小粉嫩喷水| 亚洲国产精品人久久电影| 三上悠亚电影全集免费 | 中文在线免费不卡视频| 青青草国产免费久久久下载| 久久精品国产亚洲av日韩| 国产精品美女免费视频观看| 免费无码看av的网站| 亚洲一级片在线观看| 一区二区三区四区免费视频| 亚洲日韩精品一区二区三区无码 | 亚洲国产精品成人AV无码久久综合影院| 美女被免费网站在线视频免费 | 亚洲精品无码MV在线观看| 精品女同一区二区三区免费播放 | 怡红院亚洲怡红院首页| 麻豆va在线精品免费播放| 大学生高清一级毛片免费| 亚洲an日韩专区在线| 久久精品免费全国观看国产| 亚洲国产精品综合一区在线| 久久精品人成免费|