亚洲在线久爱草,狠狠天天香蕉网,天天搞日日干久草,伊人亚洲日本欧美

首頁 慕課教程 HTTP 入門教程 HTTP 入門教程 手寫 WEB 服務器和 HTTP 協議

手寫 WEB 服務器和 HTTP 協議

本節我們將借助 Socket 實現服務的端口監聽并根據 Http 協議的請求和響應結構,實現一個簡單的 Web 服務器,加深體驗 Web 服務和 Http 協議的原理。

1. Http服務基本要素

1.1 監聽連接

瀏覽器每發起一次請求都需要跟服務端建立連接,服務端要時刻監聽有沒有客戶端連接。傳輸層協議有 TCP/UDP 兩種,實現起來并沒有強制說用哪一種,下面是官方文檔對 Http 連接的說明:

HTTP communication usually takes place over TCP/IP connections. The default port is TCP 80 .

文檔中指明了連接通常用的是 TCP, TCP 不用考慮數據包亂序,丟失這些問題,實現起來更簡單,高效。在代碼層我們可以用 Socket 來實現我們的 TCP 傳輸服務。

1.2 接收數據

Socket 監聽連接,在沒有連接到來之前一直是阻塞在 serverSocket.accept(); 有請求過來就可以運行到下面的代碼,然后可以根據我們的輸入流讀取信息,根據 Http 協議拆開獲取我們要的請求數據。

1.3 返回數據

根據業務處理完獲得返回實體數據,然后遵從 Http 協議格式構造返回的消息報文。瀏覽器獲得到的數據也會根據 Http 協議進行渲染。

2. Http報文格式

Http 協議請求報文的本質就是一堆字符串,只是這堆字符是有格式的,發送方跟接收方都需要按照這個格式來拼接和拆解內容。我們要實現一個 Web 服務,了解這個是最基本的要素。

以下截圖的報文是通過 tcpflow(一款功能強大的、基于命令行的免費開源工具)在 Linux 系統抓包獲取的。

sudo tcpflow -c port 8080

2.1 Request

http-request

request

圖中各種請求首部字段的具體含義/用途,會在下面章節中詳細講解到。

2.2 Response

一般情況下,服務器收到客戶端的請求后,就會有一個 Http 的響應消息,Http 響應也由 4 部分組成,分別是:狀態行、響應頭、空行 和 響應實體。
response

圖中的首部字段和返回內容(響應實體)中間是有一個空行的。

3. 實現

3.1 效果

demo

  • Web 服務端監聽 8090 端口;
  • 本地瀏覽器訪問 8090 頁面顯示 hello tomcat。

3.2 代碼

package com.imooc.mytomcat.tomcat;

import java.io.IOException;
import java.io.OutputStream;
import java.net.ServerSocket;
import java.net.Socket;

/**
 * Mytomcat
 *
 * @author zhourj
 * description
 */
public class Mytomcat {
    public static void main(String[] args) {
        Mytomcat server = new Mytomcat();
        server.start();
    }
    private void start(){
        try {
            //開啟一個 Socket 服務端,并監聽 8090 端口
            ServerSocket serverSocket = new ServerSocket(8090);
            do {
                //阻塞,直到有客戶端連接上,才會執行后面的邏輯
                Socket socket = serverSocket.accept();
                //處理數據
                hander(socket);
            } while (true);
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * http response
     *  第一行 協議 返回狀態
     *  第二行 媒體類型 josn/html
     *  第三行 空
     *  內容
     * @param socket
     */
    private void hander(Socket socket) throws IOException {
        //拼接返回的 request 報文
        StringBuilder responseBuilder = new StringBuilder();
        responseBuilder
		        //返回 200 狀態碼,表示請求成功
		        .append("HTTP/1.1 200 \r\n")
		        //告訴請求的客戶端,返回的內容是 text/html 格式的
                .append("Content-Type: text/html\r\n")
                //首部字段和消息實體中間的空行
                .append("\r\n")
                //內容部分
                .append("hello tomcat");
		//獲取客戶端通道的輸出流
        OutputStream outputStream = socket.getOutputStream();
        //往輸出流通道寫消息
        outputStream.write(responseBuilder.toString().getBytes());
        //流是有緩存機制的,寫消息的時候不一定立馬發出去,刷一下才能保證數據發送出去
        outputStream.flush();
        //關閉輸出流通道
        outputStream.close();
    }
}

上面的代碼初學者可以自己模仿著寫一個,相信對 Http 會有很深刻的體驗。代碼中主要是監聽連接,客戶端連接后,根據 Http 協議進行字符串的拼接返回給客戶端,客戶端瀏覽器接收到是標準的 Http 格式就會進行渲染。

4. 小結

這邊的代碼雖然很簡單,但是最核心的 Http 服務雛形已經展示出來了,成熟的 Http 服務可以在這基礎上對以下模塊進行優化:

  • 針對請求事件的 線程 / IO 優化;
  • Servlet 協議支持;
  • 配置獨立管理;
  • Http協議內容完善(比如緩存機制);
  • 支持虛擬主機配置;
  • 支持代理;
  • rewrite 機制;
  • 安全認證。