JAVA-7NIO之Socket/ServerSocket Channel

1、ServerSocketChannel

Java NIO中的 ServerSocketChannel 是一個能夠監聽新進來的TCP鏈接的通道, 就像標準IO中的ServerSocket同樣。ServerSocketChannel類在 java.nio.channels包中。java

打開 ServerSocketChannel

經過調用 ServerSocketChannel.open() 方法來打開ServerSocketChannel.服務器

關閉 ServerSocketChannel

經過調用ServerSocketChannel.close() 方法來關閉ServerSocketChannel. 網絡

監聽新進來的鏈接

經過 ServerSocketChannel.accept() 方法監聽新進來的鏈接。當 accept()方法返回的時候,它返回一個包含新進來的鏈接的 SocketChannel。所以, accept()方法會一直阻塞到有新鏈接到達。異步

一般不會僅僅只監聽一個鏈接,在while循環中調用 accept()方法. socket

固然,也能夠在while循環中使用除了true之外的其它退出準則。spa

非阻塞模式

ServerSocketChannel能夠設置成非阻塞模式。在非阻塞模式下,accept() 方法會馬上返回,若是尚未新進來的鏈接,返回的將是null。 所以,須要檢查返回的SocketChannel是不是null.如:code

    /**
     * socket server channel
     */
    @Test
    public void text2() throws IOException {
        ServerSocketChannel channel = ServerSocketChannel.open();    //新建channel
        channel.socket().bind(new InetSocketAddress(9999));     //監聽端口
        channel.configureBlocking(true);                             //設置阻塞

        while (true) {
            SocketChannel accept = channel.accept();                    //設置爲阻塞,則此方法阻塞,直到有鏈接
            //若是設置爲非阻塞,須要在這裏判斷 accept == null?
            ByteBuffer byteBuffer = ByteBuffer.allocate(1024);
            accept.read(byteBuffer);
            byteBuffer.flip();                                    //反轉
            while (byteBuffer.hasRemaining()) {                   //判斷
                System.err.println((char)byteBuffer.get());       //輸出
            }
        }
    }

 

2、SocketChannel

Java NIO中的SocketChannel是一個鏈接到TCP網絡套接字的通道。能夠經過如下2種方式建立SocketChannel:server

  1. 打開一個SocketChannel並鏈接到互聯網上的某臺服務器。
  2. 一個新鏈接到達ServerSocketChannel時,會建立一個SocketChannel。

打開 SocketChannel

下面是SocketChannel的打開方式:blog

關閉 SocketChannel

當用完SocketChannel以後調用SocketChannel.close()關閉SocketChannel:ip

從 SocketChannel 讀取數據

要從SocketChannel中讀取數據,調用一個read()的方法之一。

首先,分配一個Buffer。從SocketChannel讀取到的數據將會放到這個Buffer中。

而後,調用SocketChannel.read()。該方法將數據從SocketChannel 讀到Buffer中。read()方法返回的int值表示讀了多少字節進Buffer裏。若是返回的是-1,表示已經讀到了流的末尾(鏈接關閉了)。

寫入 SocketChannel

寫數據到SocketChannel用的是SocketChannel.write()方法,該方法以一個Buffer做爲參數。

注意SocketChannel.write()方法的調用是在一個while循環中的。Write()方法沒法保證能寫多少字節到SocketChannel。因此,咱們重複調用write()直到Buffer沒有要寫的字節爲止。

非阻塞模式

能夠設置 SocketChannel 爲非阻塞模式(non-blocking mode).設置以後,就能夠在異步模式下調用connect(), read() 和write()了。

connect()

若是SocketChannel在非阻塞模式下,此時調用connect(),該方法可能在鏈接創建以前就返回了。爲了肯定鏈接是否創建,能夠調用finishConnect()的方法。

 

write()

非阻塞模式下,write()方法在還沒有寫出任何內容時可能就返回了。因此須要在循環中調用write()。前面已經有例子了,這裏就不贅述了。

read()

非阻塞模式下,read()方法在還沒有讀取到任何數據時可能就返回了。因此須要關注它的int返回值,它會告訴你讀取了多少字節。

非阻塞模式與選擇器

非阻塞模式與選擇器搭配會工做的更好,經過將一或多個SocketChannel註冊到Selector,能夠詢問選擇器哪一個通道已經準備好了讀取,寫入等。Selector與SocketChannel的搭配使用會在後面詳講。

/**
     * socket channel
     */
    @Test
    public void test3() throws IOException {
        SocketChannel channel = SocketChannel.open();                               //新建服務端
        channel.connect(new InetSocketAddress("127.0.0.1",9999));   //鏈接服務端地址
        ByteBuffer byteBuffer = ByteBuffer.allocate(1024);  //緩衝區
        byteBuffer.put("123".getBytes());
        byteBuffer.flip();                                  //反轉
        while (byteBuffer.hasRemaining()) {                 //判斷
            channel.write(byteBuffer);
        }
    }
相關文章
相關標籤/搜索