您當前的位置:首頁 > 曲藝

深入理解HTTP的最好方式就是自己造一個輪子(1)

作者:由 Esimorp 發表于 曲藝時間:2016-12-06

本文所有程式碼均託管在Esimorp/SimpleHttpServer

我想大多數的開發者應該都知道HTTP協議是基於TCP/IP協議的,那麼在網路傳輸的過程中,

請求資料

和響應資料究竟是如何傳輸的呢?今天就讓我們來一探究竟。

public

class

HttpServer

{

public

HttpServer

int

port

throws

IOException

{

ServerSocket

serverSocket

=

new

ServerSocket

port

);

Socket

socket

=

serverSocket

accept

();

BufferedReader

input

=

new

BufferedReader

new

InputStreamReader

socket

getInputStream

()));

BufferedWriter

output

=

new

BufferedWriter

new

OutputStreamWriter

socket

getOutputStream

()));

String

line

=

null

int

index

=

0

while

((

line

=

input

readLine

())

!=

null

{

System

out

print

index

);

System

out

println

line

);

if

line

length

()

==

0

break

index

++;

}

output

write

“Hello World”

);

output

flush

();

input

close

();

output

close

();

}

}

這是一個簡單的Java的TCP Server程式,我們建立了一個HttpServer類,在

建構函式

中接受了一個int型的引數,用作這個HttpServer的監聽埠。然後我們建立了一個SocketServer繫結在傳進來的port上,然後取得SocketServer的Socket,獲取這個socket的輸入流和輸出流,因為在Http協議中大部分內容都是String型別的並且以行來分割資料,所以這裡我們用BufferedReader和BufferedWriter來操作輸入和輸出。

InputStream的read方法是阻塞的,所以當沒有資料寫入的時候程式會在while迴圈處阻塞,當有資料流入的時候才會執行while迴圈的迴圈體部分。在迴圈體中,我們將收到輸入資料中的每一行,我們用index作為行號,將每一行的內容打印出來。由於當HTTP的報文的Header塊結束的時候會有一個CRLF作為Header塊的結束標記,這裡我們先簡寫成判斷length。

當所有資料接收完畢的時候,我們將會在輸出中輸出一個

字串

“Hello World”最為一個好開頭。然後將輸入和輸出流關閉。

public

class

Main

{

public

static

void

main

String

args

[])

{

try

{

new

HttpServer

8081

);

}

catch

IOException

e

{

e

printStackTrace

();

}

}

}

在程式入口處我們建立這個HttpServer類,然後將埠繫結到8081,然後使用瀏覽器訪問我們建立的HttpServer,到底會發生什麼呢?

深入理解HTTP的最好方式就是自己造一個輪子(1)

深入理解HTTP的最好方式就是自己造一個輪子(1)

哈哈,久違的Hello World出現了,瀏覽器把我們輸出的字串正確的渲染出來了。大家可能會發現有一條請求沒有正確相應,可是我們明明只有一串字元,並沒有其它的任何內容,為什麼會又有一條請求呢?

這個

favicon。ico

檔案做建站的開發者可能會熟悉,但是做API的開發者可能不會太清楚。

這個檔案就是網站的圖示,如圖紅框處就是知乎的圖示。

深入理解HTTP的最好方式就是自己造一個輪子(1)

深入理解HTTP的最好方式就是自己造一個輪子(1)

這個圖示在html中沒有任何設定的情況下,瀏覽器預設favicon。ico在網站的根目錄,在載入完document後會再次發起請求,訪問這個檔案,而我們的伺服器只相應第一次請求,所以這次請求就會出現ERR_CONNECTION_REFUSED異常。

好了現在讓我們看看我們的伺服器輸出了什麼呢?

深入理解HTTP的最好方式就是自己造一個輪子(1)

深入理解HTTP的最好方式就是自己造一個輪子(1)

第0行:Http請求的起始行,包含了 請求方法,請求路徑,和HTTP

協議版本

,這三個內容用空格進行分割,這次請求的方法是GET 路徑是 / 也就是根目錄,HTTP協議版本是1。1

第1-9行: Http請求的首部,也就是常說的Header,這裡面放置的是該Http請求的附加資訊,每條資訊的名字和內容用冒號分割,結尾處用CRLF表示結束。

第10行: 表示Http請求的首部的

終止符

,也就是說首部到此結束。

有關於Http的首部我們以後會更詳細的說明,《

HTTP權威指南

》是一本很棒的書,有興趣的朋友可以透過讀這本書來了解更多關於Http首部的知識。

由於瀏覽器訪問URL所使用的方法是GET,所以這裡面我們沒有看到請求體,這個在以後的內容中也會出現的。

好了,到這裡我們已經學會了做了一個非常非常簡單的HTTP伺服器,當有請求的時候,這個伺服器會響應一個內容為“Hello World”的字串,然後將這個HTTP伺服器關閉。要想想,當人類文明毀滅的時候,你就變成了重建網際網路的中堅力量,想一想是不是還有一些激動呢?

下一篇文章中,我們將會了解到更多的關於HTTP報文的知識

未完待續。。。

標簽: 請求  http  我們  首部