<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                HTTP是基于TCP協議的。TCP負責數據傳輸,而HTTP只是規范了TCP傳輸的數據的格式,而這個具體的格式,請見后面給出的資料。 HTTP服務的底層實現就是socket編程。 下面基于socket編寫一個簡單的HTTP server。 ~~~ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; class SocketHandler implements Runnable { final static String CRLF = "\r\n"; // 1 private Socket clientSocket; public SocketHandler(Socket clientSocket) { this.clientSocket = clientSocket; } public void handleSocket(Socket clientSocket) throws IOException { BufferedReader in = new BufferedReader( new InputStreamReader(clientSocket.getInputStream()) ); PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(clientSocket.getOutputStream())), true ); String requestHeader = ""; String s; while ((s = in.readLine()) != null) { s += CRLF; // 2 很重要,默認情況下in.readLine的結果中`\r\n`被去掉了 requestHeader = requestHeader + s; if (s.equals(CRLF)){ // 3 此處HTTP請求頭我們都得到了;如果從請求頭中判斷有請求正文,則還需要繼續獲取數據 break; } } System.out.println("客戶端請求頭:"); System.out.println(requestHeader); String responseBody = "客戶端的請求頭是:\n"+requestHeader; String responseHeader = "HTTP/1.0 200 OK\r\n" + "Content-Type: text/plain; charset=UTF-8\r\n" + "Content-Length: "+responseBody.getBytes().length+"\r\n" + "\r\n"; // 4 問題來了:1、瀏覽器如何探測編碼 2、瀏覽器受到content-length后會按照什么方式判斷?漢字的個數?字節數? System.out.println("響應頭:"); System.out.println(responseHeader); out.write(responseHeader); out.write(responseBody); out.flush(); out.close(); in.close(); clientSocket.close(); } @Override public void run() { try { handleSocket(clientSocket); } catch(Exception ex) { ex.printStackTrace(); } } } public class MyHTTPServer { public static void main(String[] args) throws Exception { int port = 8000; ServerSocket serverSocket = new ServerSocket(port); System.out.println("啟動服務,綁定端口: " + port); ExecutorService fixedThreadPool = Executors.newFixedThreadPool(30); // 5 while (true) { // 6 Socket clientSocket = serverSocket.accept(); System.out.println("新的連接" + clientSocket.getInetAddress() + ":" + clientSocket.getPort()); try { fixedThreadPool.execute(new SocketHandler(clientSocket)); } catch (Exception e) { System.out.println(e); } } } } ~~~ 這是一個實現HTTP 1.0的服務器,對于所有的HTTP請求,會把HTTP請求頭響應回去。 這個程序說明了web服務器處理請求的基本流程,JSP、Servlet、Spring MVC等只是在 這個基礎上嫁了許多方法,以讓我們更方面的編寫web應用。web服務器不僅可以基于多線程, 也可以基于多進程、Reactor模型等。 **測試程序:** 運行上面的程序。我們使用curl訪問`http://127.0.0.1`(也可以使用瀏覽器): ~~~ $ curl -i http://127.0.0.1:8000 HTTP/1.0 200 OK Content-Type: text/plain; charset=UTF-8 Content-Length: 106 客戶端的請求頭是: GET / HTTP/1.1 User-Agent: curl/7.35.0 Host: 127.0.0.1:8000 Accept: */* ~~~ Java程序輸出: ~~~ 啟動服務,綁定端口: 8000 新的連接/127.0.0.1:36463 新的連接/127.0.0.1:36463客戶端請求頭: GET / HTTP/1.1 User-Agent: curl/7.35.0 Host: 127.0.0.1:8000 Accept: */* 響應頭: HTTP/1.0 200 OK Content-Type: text/plain; charset=UTF-8 Content-Length: 106 ~~~ **程序解析:** `// 1`:定義了HTTP頭的換行符。 `// 2`:in.readLine()的結果默認不帶換行符,這里把它加上。(這不是強制的,主要看你的程序邏輯需不需要, 這個程序的目標是把HTTP請求頭響應回去)。 `// 3`:此時s是一個空行,根據HTTP協議,整個請求頭都得到了。 `// 4`:Content-Length的值是字節的數量。 `// 5`:線程池。 `// 6`:這個循環不停監聽socket連接,使用SocketHandler處理連入的socket,而這個處理是放在線程池中的。 **HTTP 1.1:** HTTP 1.1也是在這個思路的基礎上實現的,即多個HTTP請求都在一個TCP連接中傳輸。對于HTTP 1.1,如何區分出每個HTTP請求很重要, 比較簡單的可以是用過`Content-Length`判斷一條請求是否結束。如果一個HTTP請求數據較多,往往采用Chunked方式, 可以參考[Chunked transfer encoding](https://en.wikipedia.org/wiki/Chunked_transfer_encoding)。 ## [](https://github.com/someus/another-tutorial-about-java-web/blob/master/00-02.md#http相關資料)HTTP相關資料 **網絡教程:** [菜鳥教程-HTTP教程](http://www.runoob.com/http/http-tutorial.html) [List of HTTP header fields](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields) [14 Header Field Definitions](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html) [HTTP header should use what character encoding?](http://stackoverflow.com/questions/4400678/http-header-should-use-what-character-encoding) **書籍:** [HTTP權威指南](https://github.com/someus/another-tutorial-about-java-web/blob/master)?[計算機網絡](https://github.com/someus/another-tutorial-about-java-web/blob/master)?謝希仁HTTP是基于TCP協議的。TCP負責數據傳輸,而HTTP只是規范了TCP傳輸的數據的格式,而這個具體的格式,請見后面給出的資料。 HTTP服務的底層實現就是socket編程。 下面基于socket編寫一個簡單的HTTP server。 ~~~ import java.io.BufferedReader; import java.io.BufferedWriter; import java.io.IOException; import java.io.InputStreamReader; import java.io.OutputStreamWriter; import java.io.PrintWriter; import java.net.ServerSocket; import java.net.Socket; import java.util.concurrent.Executors; import java.util.concurrent.ExecutorService; class SocketHandler implements Runnable { final static String CRLF = "\r\n"; // 1 private Socket clientSocket; public SocketHandler(Socket clientSocket) { this.clientSocket = clientSocket; } public void handleSocket(Socket clientSocket) throws IOException { BufferedReader in = new BufferedReader( new InputStreamReader(clientSocket.getInputStream()) ); PrintWriter out = new PrintWriter( new BufferedWriter( new OutputStreamWriter(clientSocket.getOutputStream())), true ); String requestHeader = ""; String s; while ((s = in.readLine()) != null) { s += CRLF; // 2 很重要,默認情況下in.readLine的結果中`\r\n`被去掉了 requestHeader = requestHeader + s; if (s.equals(CRLF)){ // 3 此處HTTP請求頭我們都得到了;如果從請求頭中判斷有請求正文,則還需要繼續獲取數據 break; } } System.out.println("客戶端請求頭:"); System.out.println(requestHeader); String responseBody = "客戶端的請求頭是:\n"+requestHeader; String responseHeader = "HTTP/1.0 200 OK\r\n" + "Content-Type: text/plain; charset=UTF-8\r\n" + "Content-Length: "+responseBody.getBytes().length+"\r\n" + "\r\n"; // 4 問題來了:1、瀏覽器如何探測編碼 2、瀏覽器受到content-length后會按照什么方式判斷?漢字的個數?字節數? System.out.println("響應頭:"); System.out.println(responseHeader); out.write(responseHeader); out.write(responseBody); out.flush(); out.close(); in.close(); clientSocket.close(); } @Override public void run() { try { handleSocket(clientSocket); } catch(Exception ex) { ex.printStackTrace(); } } } public class MyHTTPServer { public static void main(String[] args) throws Exception { int port = 8000; ServerSocket serverSocket = new ServerSocket(port); System.out.println("啟動服務,綁定端口: " + port); ExecutorService fixedThreadPool = Executors.newFixedThreadPool(30); // 5 while (true) { // 6 Socket clientSocket = serverSocket.accept(); System.out.println("新的連接" + clientSocket.getInetAddress() + ":" + clientSocket.getPort()); try { fixedThreadPool.execute(new SocketHandler(clientSocket)); } catch (Exception e) { System.out.println(e); } } } } ~~~ 這是一個實現HTTP 1.0的服務器,對于所有的HTTP請求,會把HTTP請求頭響應回去。 這個程序說明了web服務器處理請求的基本流程,JSP、Servlet、Spring MVC等只是在 這個基礎上嫁了許多方法,以讓我們更方面的編寫web應用。web服務器不僅可以基于多線程, 也可以基于多進程、Reactor模型等。 **測試程序:** 運行上面的程序。我們使用curl訪問`http://127.0.0.1`(也可以使用瀏覽器): ~~~ $ curl -i http://127.0.0.1:8000 HTTP/1.0 200 OK Content-Type: text/plain; charset=UTF-8 Content-Length: 106 客戶端的請求頭是: GET / HTTP/1.1 User-Agent: curl/7.35.0 Host: 127.0.0.1:8000 Accept: */* ~~~ Java程序輸出: ~~~ 啟動服務,綁定端口: 8000 新的連接/127.0.0.1:36463 新的連接/127.0.0.1:36463客戶端請求頭: GET / HTTP/1.1 User-Agent: curl/7.35.0 Host: 127.0.0.1:8000 Accept: */* 響應頭: HTTP/1.0 200 OK Content-Type: text/plain; charset=UTF-8 Content-Length: 106 ~~~ **程序解析:** `// 1`:定義了HTTP頭的換行符。 `// 2`:in.readLine()的結果默認不帶換行符,這里把它加上。(這不是強制的,主要看你的程序邏輯需不需要, 這個程序的目標是把HTTP請求頭響應回去)。 `// 3`:此時s是一個空行,根據HTTP協議,整個請求頭都得到了。 `// 4`:Content-Length的值是字節的數量。 `// 5`:線程池。 `// 6`:這個循環不停監聽socket連接,使用SocketHandler處理連入的socket,而這個處理是放在線程池中的。 **HTTP 1.1:** HTTP 1.1也是在這個思路的基礎上實現的,即多個HTTP請求都在一個TCP連接中傳輸。對于HTTP 1.1,如何區分出每個HTTP請求很重要, 比較簡單的可以是用過`Content-Length`判斷一條請求是否結束。如果一個HTTP請求數據較多,往往采用Chunked方式, 可以參考[Chunked transfer encoding](https://en.wikipedia.org/wiki/Chunked_transfer_encoding)。 ## [](https://github.com/someus/another-tutorial-about-java-web/blob/master/00-02.md#http相關資料)HTTP相關資料 **網絡教程:** [菜鳥教程-HTTP教程](http://www.runoob.com/http/http-tutorial.html) [List of HTTP header fields](https://en.wikipedia.org/wiki/List_of_HTTP_header_fields) [14 Header Field Definitions](http://www.w3.org/Protocols/rfc2616/rfc2616-sec14.html) [HTTP header should use what character encoding?](http://stackoverflow.com/questions/4400678/http-header-should-use-what-character-encoding) **書籍:** [HTTP權威指南](https://github.com/someus/another-tutorial-about-java-web/blob/master)?[計算機網絡](https://github.com/someus/another-tutorial-about-java-web/blob/master)?謝希仁
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看