SocketChannel簡述


前言

在前面的Channel概述的分類中提到過SocketChannel主要是用來基於TCP通信的通道。這篇文章詳細介紹下SocketChannel

  • SocketChannel是什么
  • SocketChannel特點
  • SocketChannel的使用

SocketChannel

A selectable channel for stream-oriented connecting sockets.

以上是Java docs中對於SocketChannel的描述:SocketChannel是一種面向流連接只sockets套接字的可選擇通道。從這里可以看出:

  • SocketChannel是用來連接Socket套接字
  • SocketChannel主要用途用來處理網絡I/O的通道
  • SocketChannel是基於TCP連接傳輸
  • SocketChannel實現了可選擇通道,可以被多路復用的

SocketChannel特點

SocketChannel具有以下的特征:

  1. 對於已經存在的socket不能創建SocketChannel
  2. SocketChannel中提供的open接口創建的Channel並沒有進行網絡級聯,需要使用connect接口連接到指定地址
  3. 未進行連接的SocketChannle執行I/O操作時,會拋出NotYetConnectedException
  4. SocketChannel支持兩種I/O模式:阻塞式和非阻塞式
  5. SocketChannel支持異步關閉。如果SocketChannel在一個線程上read阻塞,另一個線程對該SocketChannel調用shutdownInput,則讀阻塞的線程將返回-1表示沒有讀取任何數據;如果SocketChannel在一個線程上write阻塞,另一個線程對該SocketChannel調用shutdownWrite,則寫阻塞的線程將拋出AsynchronousCloseException
  6. SocketChannel支持設定參數
參數名 作用描述
SO_SNDBUF 套接字發送緩沖區大小
SO_RCVBUF 套接字接收緩沖區大小
SO_KEEPALIVE 保活連接
O_REUSEADDR 復用地址
SO_LINGER 有數據傳輸時延緩關閉Channel (只有在非阻塞模式下有用)
TCP_NODELAY 禁用Nagle算法

SocketChannel的使用

1.創建SocketChannel

方式1.
SocketChannel socketChannel = SocketChannel.open(new InetSocketAddress("www.baidu.com", 80));

方式2. 
SocketChannel socketChannel = SocketChannel.open();
socketChannel.connect(new InetSocketAddress("www.baidu.com", 80));

直接使用有參open api或者使用無參open api,但是在無參open只是創建了一個SocketChannel對象,並沒有進行實質的tcp連接。

2.連接校驗

socketChannel.isOpen();      // 測試SocketChannel是否為open狀態
socketChannel.isConnected();    //測試SocketChannel是否已經被連接
socketChannel.isConnectionPending();    //測試SocketChannel是否正在進行連接
socketChannel.finishConnect();    //校驗正在進行套接字連接的SocketChannel是否已經完成連接

3.讀寫模式

前面提到SocketChannel支持阻塞和非阻塞兩種模式:

socketChannel.configureBlocking(false);

主要是通過以上方法設置SocketChannel的讀寫模式。false表示非阻塞,true表示阻塞。

4.讀寫

SocketChannel socketChannel = SocketChannel.open(
new InetSocketAddress("www.baidu.com", 80));
ByteBuffer byteBuffer = ByteBuffer.allocate(16);
socketChannel.read(byteBuffer);
socketChannel.close();
System.out.println("test end!");

以上為阻塞式讀,當執行到read出,線程將阻塞,控制台將無法打印test end!。

SocketChannel socketChannel = SocketChannel.open(
new InetSocketAddress("www.baidu.com", 80));
socketChannel.configureBlocking(false);
ByteBuffer byteBuffer = ByteBuffer.allocate(16);
socketChannel.read(byteBuffer);
socketChannel.close();
System.out.println("test end!");

以上為非阻塞讀,控制台將打印test end!。

讀寫都是面向緩沖區,這個讀寫方式與前文中的FileChannel一樣,這里不再贅述。

5.設置和獲取參數

socketChannel.setOption(StandardSocketOptions.SO_KEEPALIVE, Boolean.TRUE)
    .setOption(StandardSocketOptions.TCP_NODELAY, Boolean.TRUE);

通過setOptions方法可以設置socket套接字的相關參數。

socketChannel.getOption(StandardSocketOptions.SO_KEEPALIVE)
socketChannel.getOption(StandardSocketOptions.SO_RCVBUF)

可以通過getOption獲取相關參數的值。如默認的接收緩沖區大小是8192byte。

前面提到SocketChannel還支持多路復用,但是多路復用在后續章節中會介紹到,故此將SocketChannel注冊到通道上,多路復用的使用,在接下來文章中會介紹。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM