1. 程式人生 > >NIO系列(四)——socket通道和serversocket通道

NIO系列(四)——socket通道和serversocket通道

SocketChannel

SocketChannel是一個連線到tcp網路套接字的通道。可以通過以下2中方式建立

1.開啟一個SocketChannel並連線到網際網路上的某臺伺服器。

SocketChannel client = SocketChannel.open(new InetSocketAddress("127.0.0.1",10699));

2.ServerSocketChannel獲得一個網路連線。

SocketChannel connctClient = server.accept();

建立SocketChannel

通過SocketChannel.Open()方法建立通道,open()方法可以傳入連線物件的引數。

SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("192.168.1.107",9999));

關閉SocketChannel

通過close()方法關閉通道。

socketChannel.close();

socketChannel接收資訊

可以通過read()方法把通道資料讀到快取中。

ByteBuffer bBuffer = ByteBuffer.allocate(48);
int readSize;
do {
    readSize = socketChannel.read(bBuffer);
    bBuffer.flip();
    System.out.println(Charset.forName("UTF-8").decode(bBuffer));
    bBuffer.clear();
} while (readSize != -1);

read()返回的int值表示讀到快取資料的長度,當返回值為-1時,表示到了流的末尾。

SocketChannel傳送資訊

通過write()方法將快取資料寫入到通道內,write()無法保證一次向通道中寫入多少資料,所以要迴圈判斷hasRemainning(),直到沒有資料寫入。

ByteBuffer bBuffer = ByteBuffer.wrap(("伺服器" + server + "連線成功").getBytes());
while (bBuffer.hasRemaining()){
    socketChannel.write(bBuffer);
}

非阻塞設定

SocketChannel可以通過configureBlocking()方法設定成非阻塞。

socketChannel.configureBlocking(false);

例子

這個例子是與192.168.1.107:9999建立連線並接收一次傳送資料。

public voidtestClient() {
    try {
       SocketChannelsocketChannel= SocketChannel.open();
       socketChannel.configureBlocking(false);
       socketChannel.connect(new InetSocketAddress("192.168.1.107",9999));
       ByteBufferbBuffer= ByteBuffer.allocate(48);
       int readSize;
       do {
           readSize = socketChannel.read(bBuffer);
           bBuffer.flip();
           System.out.println(Charset.forName("UTF-8").decode(bBuffer));
           bBuffer.clear();
       }while(readSize!= -1);
       socketChannel.close();
    }catch(IOException e) {
       e.printStackTrace();
    }
}

ServerSocketChannel

Java NIO的ServerSocketChannel是一個可以監聽新進來的TCP連線的通道,就像標準IO的ServerSocket一樣。

建立ServerSocketChannel

通過ServerSocketChannel.open()建立通道

ServerSocketChannel server = ServerSocketChannel.open();
server.socket().bind(new InetSocketAddress(9999));

server.socket().bind(SocketAddressendpoint, int backlog)可以傳兩個引數,第二個引數是,限制最大連線數。

獲得連線

通過accept()方法,獲得socket連線

SocketChannel socketChannel = server.accept();

傳送資料和接收資料都通過SocketChannel進行。

關閉ServerSocketChannel

通過close()方法關閉通道

server.close();

非阻塞設定

ServerSocketChannel可以設定成非阻塞模式。在非阻塞模式下,accept會立即返回,所以要判斷SocketChannel是否為空。

server.configureBlocking(false);
while (true){
    SocketChannelsocketChannel= server.accept();
    if (socketChannel != null) {
      
    }
}

例子

這個例子先繫結監聽9999埠,但有socket連線時,會發送一條資料。

public voidtestServer() {
    try {
       ServerSocketChannelserver= ServerSocketChannel.open();
       server.socket().bind(newInetSocketAddress(9999));
       System.out.println("服務端啟動成功");
       server.configureBlocking(false);
       while (true) {
           SocketChannelsocketChannel= server.accept();
           if (socketChannel != null) {
              System.out.println(socketChannel + "連線成功");
              ByteBufferbBuffer= ByteBuffer.wrap(("伺服器" + server + "連線成功").getBytes());
              while (bBuffer.hasRemaining()) {
                  socketChannel.write(bBuffer);
              }
           }
       }
    }catch(IOException e) {
       e.printStackTrace();
    }
}