BIO

在這里使用 java代碼,記錄 BIO 的理解。要使用 jdk1.4 版本的才能在追蹤的時(shí)候看出本質(zhì)。高版本的jdk 內(nèi)部已經(jīng)有了優(yōu)化,會(huì)使用poll的方式來(lái)執(zhí)行。Block IO。

linux中使用 strace 命令,可以追蹤程序的系統(tǒng)調(diào)用。

追蹤示例.png

import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;

public class SocketBIO {
    public static void main(String[] args) throws IOException {
        ServerSocket server = new ServerSocket(9090, 20);
        System.out.println("服務(wù)已開啟");
        while (true) {
            Socket client = server.accept();//阻塞1,等待接收連接
            System.out.println("客戶端已連上,端口號(hào):" + client.getPort());
            //一旦獲取到了一個(gè)client,分一個(gè)線程出去處理
            new Thread(() -> {
                InputStream in = null;
                try {
                    in = client.getInputStream();//獲取輸入流,字節(jié)
                    //將字節(jié)轉(zhuǎn)換為字符并讀取
                    BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(in));
                    while (true) {
                        String s = bufferedReader.readLine();//阻塞2,獲取該線程連接的輸入
                        if (null != s) {
                            System.out.println("輸入的內(nèi)容是:" + s);
                        } else {
                            client.close();
                        }
                    }
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }).start();
        }
    }
}

以上代碼執(zhí)行后,會(huì)有兩個(gè)阻塞,線程一直被掛起,等待連接和輸入
strace追蹤后可以發(fā)現(xiàn)下圖是主線程等待連接的阻塞:

主線程的阻塞.png

開啟一個(gè)socket,返回一個(gè)變量3,為3綁定端口號(hào),然后監(jiān)聽,做write系統(tǒng)調(diào)用,3這個(gè)線程開始等待連接。
上圖中的 2531行中的write函數(shù)就是系統(tǒng)調(diào)用,參數(shù)和上面代碼的輸出不一致。
當(dāng)使用nc命令連接上這個(gè)服務(wù)后,將會(huì)返回一個(gè)客戶端,進(jìn)入線程中,主線程繼續(xù) accept
從追蹤命令當(dāng)中可以看到,java當(dāng)中的新啟動(dòng)一個(gè)線程,在linux中,實(shí)際上是開啟了一個(gè)進(jìn)程。新進(jìn)程是從主進(jìn)程中clone出來(lái)的。
新線程的阻塞.png

返回來(lái)個(gè)1590進(jìn)程號(hào)。

繼續(xù)追蹤1590進(jìn)程號(hào)可以發(fā)現(xiàn)還有一個(gè)recv阻塞了。對(duì)應(yīng)的是代碼的這一行bufferedReader.readLine()

總結(jié).png

這里的變量5是新線程的client。

image.png

  1. 因?yàn)?code>BIO模式有blocking,所以只能以拋出線城的方式去處理連接,不然在主線程只能接收一個(gè)連接。程序員的代碼是無(wú)法解決這個(gè)問(wèn)題的,因?yàn)橄胍B接多個(gè),必然只能拋出多個(gè)線程,因?yàn)橛凶枞?/li>
  2. 每輪一下,還會(huì)涉及到系統(tǒng)調(diào)用,accept,clone,recv都是系統(tǒng)調(diào)用函數(shù)。所以要解決這個(gè)問(wèn)題,只能從內(nèi)核下手。所以有了后來(lái)的NIO,noblock。
    以上兩點(diǎn)就是BIO的弊端
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容