探索Java通訊面試的奧祕:揭祕IO模型、選擇器和網路協定,瞭解面試中的必備知識點!

2023-07-27 12:14:02

瞭解常見的TCP/UDP

TCP(Transmission Control Protocol)是一種面向連線的可靠的傳輸協定。類似於打電話,它通過建立一個連線和保證資料的可靠傳輸來提高通訊的可靠性。然而,由於要確保資料的可靠性,TCP協定會增加網路負擔,效率相對較低。

UDP(User Datagram Protocol)是一種無連線、不可靠的傳輸協定。類似於廣播,UDP協定可以實現一對多的通訊,且由於沒有連線的建立和資料的確認,所以傳輸效率相對較高。然而,由於缺乏連線和確認機制,UDP的可靠性較差。

在瞭解TCP和UDP之後,常見的面試題包括TCP的三次握手和四次揮手。為什麼要採用三次握手而不是兩次握手呢?這是因為網路傳輸本身具有不穩定性,例如網路超時和網路阻塞等問題。如果只進行兩次握手,當伺服器端返回第二次握手給使用者端後,無法確定使用者端是否成功建立連線。因此,必須進行第三次握手,以確保使用者端接收到了連線請求。否則,如果使用者端由於網路原因導致丟失了此次連線請求,伺服器將一直等待該連線的空閒超時才會關閉請求,這將嚴重消耗伺服器資源。

四次揮手也是類似於三次握手的原因。由於網路傳輸的不穩定性,斷開連線時需要確保雙方都收到斷開請求。在四次揮手中,首先使用者端傳送斷開連線請求,然後伺服器端傳送確認收到請求的訊息,接著伺服器端傳送斷開連線請求,最後使用者端傳送確認收到請求的訊息,完成連線的斷開。這樣可以確保雙方都能正確處理斷開連線的操作。

瞭解BIO、NIO、AIO

BIO是最簡單的一種I/O模型,它採用同步阻塞方式進行通訊。每個使用者端連線都需要獨立的執行緒進行處理,當有大量的並行請求時,執行緒數量會急劇增加,導致資源消耗增加,效能下降。

NIO是相對複雜的一種I/O模型,它使用了Channel、Selector和Buffer來實現非阻塞的通訊。通過Selector的多路複用機制,可以使用一個執行緒處理多個使用者端連線,從而提高並行能力。但是,NIO適合處理短請求,如果長時間佔用I/O,可能會導致伺服器資源耗盡。

以下是使用NIO實現一個簡單的伺服器範例:

import java.io.IOException;
import java.net.InetSocketAddress;
import java.nio.ByteBuffer;
import java.nio.channels.ServerSocketChannel;
import java.nio.channels.SelectionKey;
import java.nio.channels.Selector;
import java.nio.channels.SocketChannel;
import java.util.Iterator;

public class NioServerExample {
    public static void main(String[] args) throws IOException {
        // 建立ServerSocketChannel,並繫結埠
        ServerSocketChannel serverSocketChannel = ServerSocketChannel.open();
        serverSocketChannel.socket().bind(new InetSocketAddress(8080));
        serverSocketChannel.configureBlocking(false);

        // 建立Selector,並將ServerSocketChannel註冊到Selector上
        Selector selector = Selector.open();
        serverSocketChannel.register(selector, SelectionKey.OP_ACCEPT);

        while (true) {
            // 監聽事件
            selector.select();

            // 處理事件
            Iterator<SelectionKey> keyIterator = selector.selectedKeys().iterator();
            while (keyIterator.hasNext()) {
                SelectionKey key = keyIterator.next();
                keyIterator.remove();

                if (key.isAcceptable()) {
                    // 接受使用者端連線
                    ServerSocketChannel serverChannel = (ServerSocketChannel) key.channel();
                    SocketChannel socketChannel = serverChannel.accept();
                    socketChannel.configureBlocking(false);
                    socketChannel.register(selector, SelectionKey.OP_READ);
                } else if (key.isReadable()) {
                    // 讀取使用者端資料
                    SocketChannel socketChannel = (SocketChannel) key.channel();
                    ByteBuffer buffer = ByteBuffer.allocate(1024);
                    int bytesRead = socketChannel.read(buffer);
                    if (bytesRead == -1) {
                        // 使用者端關閉連線
                        socketChannel.close();
                    } else {
                        buffer.flip();
                        byte[] data = new byte[buffer.remaining()];
                        buffer.get(data);
                        String message = new String(data);
                        System.out.println("Received message: " + message);

                        // 響應使用者端
                        ByteBuffer responseBuffer = ByteBuffer.wrap("Hello, client!".getBytes());
                        socketChannel.write(responseBuffer);
                    }
                }
            }
        }
    }
}

AIO相對於NIO來說簡單一些,但是由於底層需要作業系統的支援,所以應用範圍相對較小。AIO是非同步非阻塞的I/O模型,在NIO的基礎上,通過另外的執行緒來處理業務的返回值,從而實現非同步操作。


JAVA NIO的核心元件

JAVA NIO的核心元件包括緩衝區(buffer)、通道(channel)和選擇器(selector)。

  • 緩衝區用於儲存使用者端與伺服器端互動的資料資訊,
  • 而通道類似於流,每個使用者端都會有一個獨立的通道。
  • 選擇器是多路複用的關鍵,它能夠找出具有事件的通道,並將其交給伺服器執行緒進行處理。

通過這些核心元件,JAVA NIO模型實現了高效的非阻塞I/O操作,提升了伺服器的並行處理能力。

select、poll和epoll的比較與應用

select、poll和epoll是Linux系統中的三種I/O多路複用機制。它們的目的是為了實現高效的事件驅動程式設計,以便在多個I/O操作中選擇可讀、可寫或異常事件。

檔案描述符是維護程序開啟檔案的記錄表。每個開啟的檔案都會被分配一個唯一的檔案描述符。

  • select是最古老的機制之一,它可以同時監視多個檔案描述符的狀態變化。但是,select有一些缺點,例如每次呼叫時都需要將檔案描述符集合從使用者空間拷貝到核心空間,效率較低。此外,select支援的檔案描述符數量有限。
  • poll是select的改進版本,它通過一個pollfd結構體陣列來傳遞檔案描述符資訊給核心,避免了select中每次呼叫都需要拷貝的問題。poll也支援更多的檔案描述符,但是隨著檔案描述符數量的增加,效能會有所下降。
  • epoll是在Linux 2.6核心中引入的新機制,它通過epoll_ctl和epoll_wait函數來註冊和等待事件。epoll使用一個事件陣列來儲存被監視的檔案描述符和事件狀態,只需要在註冊時將檔案描述符新增到事件陣列中,而不需要像select和poll一樣在每次呼叫時傳遞整個檔案描述符集合。這使得epoll在大規模並行情況下具有更高的效能。

HTTP vs HTTPS:理解兩者之間的區別與安全性

安全性:

  • HTTP是明文協定,資料在傳輸過程中不加密,容易被第三方截獲和竊聽。
  • HTTPS通過使用SSL(Secure Sockets Layer)或TLS(Transport Layer Security)協定對資料進行加密和身份驗證,提供更高的安全性。

埠號:

  • HTTP預設使用埠號80進行通訊
  • HTTPS預設使用埠號443進行通訊

證書:

  • HTTPS使用數位憑證來驗證伺服器的身份。證書由可信的第三方機構頒發,用於確保通訊雙方的身份和資料的完整性。
  • HTTP不需要使用證書,無法驗證伺服器的身份。

HTTPS協定增加了伺服器和使用者端之間的計算和通訊負擔,使得伺服器在處理大量請求時更容易受到壓力。雖然HTTPS可以提供一定程度的安全保護,但也會增加伺服器的負擔,使得伺服器更容易受到DDoS攻擊。

總結

通過深入探索Java通訊面試的奧祕,我們將揭祕Java中的三種I/O模型(BIO、NIO和AIO)、選擇器(select、poll和epoll)以及網路協定(如HTTP和HTTPS),幫助您瞭解在面試中必備的知識點。這些知識點對於網路程式設計和系統安全方面的求職者來說至關重要,掌握它們將為您的職業發展打下堅實的基礎!