欧美bbbwbbbw肥妇,免费乱码人妻系列日韩,一级黄片

基于Java實現(xiàn)一個自己的HTTP瀏覽器

 更新時間:2024年01月29日 15:15:42   作者:縱橫千里,捭闔四方  
這篇文章主要為大家詳細介紹了如何基于Java實現(xiàn)一個自己的HTTP瀏覽器,文中的示例代碼講解詳細,感興趣的小伙伴可以跟隨小編一起學(xué)習(xí)一下

在討論HTTP協(xié)議的具體請求和響應(yīng)頭字段之前,讓我們先來利用以前所學(xué)的知識來實現(xiàn)一個HTTP模擬器。所謂HTTP模擬器就是可以在用戶輸入HTTP的請求消息后,由這個模擬器將HTTP請求發(fā)送給相應(yīng)的服務(wù)器,再接收服務(wù)器的響應(yīng)消息。這個HTTP模擬器有幾下特點:

1.  可以手工輸入HTTP請求,并向服務(wù)器發(fā)送。

2.  接收服務(wù)器的響應(yīng)消息。

3.  消息頭和實體內(nèi)容分段顯示,也就是說,并不是象Telnet等客戶端一樣將HTTP響應(yīng)消息全部顯示,而是先顯示消息頭,然后由用戶決定是否顯示實體內(nèi)容。

4.  集中發(fā)送請求。這個HTTP模擬器和Telnet不同的是,并不是一開始就連接服務(wù)器,而是將域名、端口以及HTTP請求消息都輸完后,才連接服務(wù)器,并將這些請求發(fā)送給服務(wù)器。這樣做的可以預(yù)防服務(wù)器提前關(guān)閉網(wǎng)絡(luò)連接的現(xiàn)象。

5. 可以循環(huán)做上述的操作。

從以上的描述看,要實現(xiàn)這個HTTP模擬器需要以下五步:

  • 主線程里建立一個死循環(huán)的while,在循環(huán)內(nèi)部是一個請求/響應(yīng)對。這樣就可以向服務(wù)器發(fā)送多次請求/響應(yīng)以了。下面的四步都是被包括在循環(huán)內(nèi)部的。
  • 從控制臺讀取域名和端口,這個功能可以由readHostAndPort(...)來完成。
  • 從控制臺讀取HTTP請求消息,這個功能由readHttpRequest(...)來完成。
  • 向服務(wù)器發(fā)送HTTP請求消息,這個功能由sendHttpRequest()來完成。
  • 讀取服務(wù)器回送的HTTP響應(yīng)消息,這個功能由readHttpResponse(...)來完成。

下面我們就來逐步實現(xiàn)這五步:

1.主線程循環(huán)體

在建立這個循環(huán)之前,先建立一個中叫HttpSimulator的類,并在這個類中定義一個run方法用來運行這個程序。實現(xiàn)代碼如下:

public class HttpSimulator {
    private Socket socket;
    private int port = 80;
    private String host = "localhost";
    private String request = ""; // HTTP請求消息 012
    private boolean isPost, isHead;
 
    public void run() throws Exception {
        BufferedReader reader = new BufferedReader(new InputStreamReader(System.in));
        while (true)  // 開始大循環(huán)
        {
            try {
                if (!readHostAndPort(reader)) break;
                readHttpRequest(reader);
                sendHttpRequest();
                readHttpResponse(reader);
            } catch (Exception e) {
                System.out.println("err:" + e.getMessage());
            }
 
        }
    }
 
    public static void main(String[] args) throws Exception {
        new HttpSimulator().run();
 
    }

從上面的代碼可以看出,我們分別調(diào)用了上述的四個方法。這些方法的具體實現(xiàn)將在后面討論。上面的代碼除了調(diào)用這四個核心方法外,還做了一些準(zhǔn)備工作。在008至012行定義了一些以后要用到的變量。在016和017行使用控制臺的輸入流建立了BufferedReader對象,通過這個對象,可以直接從控制臺讀取字符串,而不是一個個地字節(jié)。

2.readHostAndPort()方法的實現(xiàn)

這個方法的主要功能是從控制臺讀取域名和端口。域名和端口通過":"隔開,":"和域名以及端口之間不能有空格。當(dāng)從控制臺讀取一個"q"時,這個函數(shù)返回false,表示程序可以退出了,否則返回true,表示輸入的域名和端口是正確的。這個方法的實現(xiàn)代碼如下:

    private boolean readHostAndPort(BufferedReader consoleReader) throws Exception {
        System.out.print("host:port>");
        String[] ss = null;
        String s = consoleReader.readLine();
        if (s.equals("q")) return false;
        else {
            ss = s.split("[:]");
            if (!ss[0].equals("")) host = ss[0];
            if (ss.length > 1) port = Integer.parseInt(ss[1]);
            System.out.println(host + ":" + String.valueOf(port));
            return true;
        }
    }

上面的代碼,我們做一個分析:

這個方法有一個BufferedReader類型的參數(shù),這個參數(shù)的值就是在HttpSimulator.java中的第016和017行根據(jù)控制臺輸入流建立的BufferedReader對象。

這輸出HTTP模擬器的控制符,就象Windows的控制臺的"C:">"一樣。

consoleReader.readLine()從控制臺讀取一行字符串。

ss = s.split("[:]") 通過字符串的split方法和響應(yīng)的正則表示式("[:]")將域名和端口分開。域名的默認(rèn)值是localhost,端口的默認(rèn)值是80。 

3.readHttpRequest()方法的實現(xiàn)

這個方法的主要功能是從控制臺讀取HTTP請求消息,如果輸入一個空行,表示請求消息頭已經(jīng)輸完;如果使用的是POST方法,還要輸入POST請求的實體內(nèi)容。這個方法的實現(xiàn)代碼如下:

    private void readHttpRequest(BufferedReader consoleReader) throws Exception {
        System.out.println("請輸入HTTP請求:");
        String s = consoleReader.readLine();
        request = s + "\r\n";
        boolean isPost = s.substring(0, 4).equals("POST");
        boolean isHead = s.substring(0, 4).equals("HEAD");
        while (!(s = consoleReader.readLine()).equals("")) {
            request = request + s + "\r\n";
        }
        request = request + "\r\n";
        if (isPost) {
            System.out.println("請輸入POST方法的內(nèi)容:");
            s = consoleReader.readLine();
            request = request + s;
 
        }
    }

上面的代碼,我們簡單解釋一下:

consoleReader.readLine() 讀入HTTP請求消息的第一行。

isPost 和isHead 用于確定所輸入的請求方法是不是POST和HEAD。之后的代碼讀入HTTP請求消息的其余行。

if (isPost) 代碼段的功能是:如果HTTP請求使用的是POST方法,要求用戶繼續(xù)輸入HTTP請求的實體內(nèi)容。

4.sendHttpRequest()方法的實現(xiàn)

這個方法的功能是將request變量中的HTTP請求消息發(fā)送到服務(wù)器。下面是這個方法的實現(xiàn)代碼:

   private void sendHttpRequest() throws Exception {
        socket = new Socket();
        socket.setSoTimeout(10 * 1000); //設(shè)置讀取數(shù)據(jù)超時為10秒。
        System.out.println("正在連接服務(wù)器");
        socket.connect(new InetSocketAddress(host, port), 10 * 1000); //超時時間
        System.out.println("服務(wù)器連接成功!");
        OutputStream out = socket.getOutputStream();
        OutputStreamWriter writer = new OutputStreamWriter(out);
        writer.write(request);
        writer.flush();
 
    }

5.readHttpResponse(...)方法的實現(xiàn)

這個方法的主要功能是從服務(wù)器讀取返回的響應(yīng)消息。首先讀取了響應(yīng)消息頭,然后要求用戶輸入Y或N以確定是否顯示響應(yīng)消息的實體內(nèi)容。這個程序之所以這樣做,主要有兩個原因:

(1) 為了研究HTTP協(xié)議。

(2) 由于本程序是以字符串形式顯示響應(yīng)消息的,因此,如果用戶請求了一個二進制Web資源,如一個rar文件,那么實體內(nèi)容將會顯示亂碼。所以在顯示完響應(yīng)消息頭后由用戶決定是否顯示實體內(nèi)容。

這個方法的實現(xiàn)代碼如下: 

 private void readHttpResponse(BufferedReader consoleReader) {
        String s = "";
        try {
            InputStream in = socket.getInputStream();
            InputStreamReader inReader = new InputStreamReader(in);
            BufferedReader socketReader = new BufferedReader(inReader);
            System.out.println("---------HTTP頭---------");
 
            boolean b = true; // true: 未讀取消息頭 false: 已經(jīng)讀取消息頭 011
            while ((s = socketReader.readLine()) != null) {
                if (s.equals("") && b == true && !isHead) {
                    System.out.println("------------------------");
                    b = false;
                    System.out.print("是否顯示HTTP的內(nèi)容(Y/N):");
                    String choice = consoleReader.readLine();
                    if (choice.equals("Y") || choice.equals("y"))   {
                        System.out.println("---------HTTP內(nèi)容---------");
                        continue;
 
                    }                    else break;
 
                } else System.out.println(s);
 
            }
        } catch (Exception e) {
            System.out.println("err:" + e.getMessage());
 
        } finally {
            try {
                socket.close();
 
            } catch (Exception e) {
 
            }
        } System.out.println("------------------------");
 
    }

在上面的代碼中013行是最值得注意的。其中s.equals("")表示讀入一個空行(表明消息頭已經(jīng)結(jié)束);由于在實體內(nèi)容中也可以存在空行,因此,b == true來標(biāo)記消息頭是否已經(jīng)被讀過,當(dāng)讀完消息頭后,將b設(shè)為false,如果以后再遇到空行,就不會當(dāng)成消息頭來處理了。當(dāng)HTTP請求使用HEAD方法時,服務(wù)器只返回響應(yīng)消息頭;因此,使用!isHead來保證使用HEAD發(fā)送請求時不顯示響應(yīng)消息的內(nèi)容實體。

現(xiàn)在我們已經(jīng)實現(xiàn)了這個HTTP模擬器,下面讓我們來運行并測試它。 

我們將上面的代碼執(zhí)行起來,然后會有個輸入的提示:

我們輸入www.csdn.net

然后繼續(xù)分行輸入如下的HTTP請求消息:

GET / HTTP/1.1
Host: www.csdn.net

之后根據(jù)提示輸入Y,運行的結(jié)果如下所示:

------------------------
是否顯示HTTP的內(nèi)容(Y/N):Y
---------HTTP內(nèi)容---------
<html>
<head><title>400 Bad Request</title></head>
<body>
<center><h1>400 Bad Request</h1></center>
<hr><center>WAF</center>
</body>
</html>

到此我們就實現(xiàn)了一個簡單的HTTP瀏覽器了。

到此這篇關(guān)于基于Java實現(xiàn)一個自己的HTTP瀏覽器的文章就介紹到這了,更多相關(guān)Java實現(xiàn)HTTP瀏覽器內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!

相關(guān)文章

  • xxl-job定時任務(wù)配置應(yīng)用及添加到springboot項目中實現(xiàn)動態(tài)API調(diào)用

    xxl-job定時任務(wù)配置應(yīng)用及添加到springboot項目中實現(xiàn)動態(tài)API調(diào)用

    XXL-JOB是一個分布式任務(wù)調(diào)度平臺,其核心設(shè)計目標(biāo)是開發(fā)迅速、學(xué)習(xí)簡單、輕量級、易擴展,本篇文章主要是對xuxueli的xxl-job做一個簡單的配置,以及將其添加到自己已有的項目中進行api調(diào)用,感興趣的朋友跟隨小編一起看看吧
    2024-04-04
  • 解決javac不是內(nèi)部或外部命令,也不是可運行程序的報錯問題

    解決javac不是內(nèi)部或外部命令,也不是可運行程序的報錯問題

    在學(xué)著使用Java的命令行來編譯java文件的時候,遇到了這個問題,本文主要介紹了解決javac不是內(nèi)部或外部命令,也不是可運行程序的報錯問題,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2022-04-04
  • SpringBean和Controller實現(xiàn)動態(tài)注冊與注銷過程詳細講解

    SpringBean和Controller實現(xiàn)動態(tài)注冊與注銷過程詳細講解

    這篇文章主要介紹了SpringBean和Controller實現(xiàn)動態(tài)注冊與注銷過程,文中通過示例代碼介紹的非常詳細,對大家的學(xué)習(xí)或者工作具有一定的參考學(xué)習(xí)價值,需要的朋友們下面隨著小編來一起學(xué)習(xí)吧
    2023-02-02
  • java實現(xiàn)微信小程序加密數(shù)據(jù)解密算法

    java實現(xiàn)微信小程序加密數(shù)據(jù)解密算法

    這篇文章主要為大家詳細介紹了java實現(xiàn)微信小程序加密數(shù)據(jù)解密算法,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2018-09-09
  • 6種SpringBoot解決跨域請求的方法整理

    6種SpringBoot解決跨域請求的方法整理

    跨域資源共享是一種標(biāo)準(zhǔn)機制,允許服務(wù)器聲明哪些源可以訪問其資源,在SpringBoot應(yīng)用中,有多種方式可以解決跨域問題,本文主要介紹了6種常見的解決方案,大家可以根據(jù)需求自行選擇
    2025-04-04
  • 使用Maven中的scope總結(jié)

    使用Maven中的scope總結(jié)

    這篇文章主要介紹了使用Maven中的scope總結(jié),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2022-06-06
  • Java中如何獲取圖片文件格式(后綴)

    Java中如何獲取圖片文件格式(后綴)

    這篇文章主要介紹了Java中如何獲取圖片文件格式(后綴),具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教
    2023-06-06
  • java實現(xiàn)簡單斗地主(看牌排序)

    java實現(xiàn)簡單斗地主(看牌排序)

    這篇文章主要介紹了java實現(xiàn)簡單斗地主,看牌進行排序,文中示例代碼介紹的非常詳細,具有一定的參考價值,感興趣的小伙伴們可以參考一下
    2010-11-11
  • Java中StringBuilder常用構(gòu)造方法解析

    Java中StringBuilder常用構(gòu)造方法解析

    這篇文章主要介紹了Java中StringBuilder常用構(gòu)造方法解析,StringBuilder是一個可標(biāo)的字符串類,我們可以吧它看成是一個容器這里的可變指的是StringBuilder對象中的內(nèi)容是可變的,需要的朋友可以參考下
    2024-01-01
  • Spring基于注解整合Redis完整實例

    Spring基于注解整合Redis完整實例

    這篇文章主要介紹了Spring基于注解整合Redis完整實例,具有一定的參考價值,感興趣的小伙伴們可以參考一下。
    2017-04-04

最新評論