溫馨提示×

您好,登錄后才能下訂單哦!

密碼登錄×
登錄注冊(cè)×
其他方式登錄
點(diǎn)擊 登錄注冊(cè) 即表示同意《億速云用戶服務(wù)條款》

基于Python怎么編寫(xiě)一個(gè)簡(jiǎn)單的http服務(wù)器

發(fā)布時(shí)間:2023-04-25 10:09:35 來(lái)源:億速云 閱讀:105 作者:iii 欄目:開(kāi)發(fā)技術(shù)

本篇內(nèi)容介紹了“基于Python怎么編寫(xiě)一個(gè)簡(jiǎn)單的http服務(wù)器”的有關(guān)知識(shí),在實(shí)際案例的操作過(guò)程中,不少人都會(huì)遇到這樣的困境,接下來(lái)就讓小編帶領(lǐng)大家學(xué)習(xí)一下如何處理這些情況吧!希望大家仔細(xì)閱讀,能夠?qū)W有所成!

什么是http

http是一個(gè)應(yīng)用層協(xié)議,準(zhǔn)確的來(lái)說(shuō)是基于TCP/IP4層網(wǎng)絡(luò)協(xié)議中的傳輸層中的TCP應(yīng)用層協(xié)議。

額,4層模型大概是這樣的:

基于Python怎么編寫(xiě)一個(gè)簡(jiǎn)單的http服務(wù)器

在網(wǎng)絡(luò)通信中,用戶的數(shù)據(jù)是以報(bào)文來(lái)傳輸?shù)模窃趯?shí)際通信中,每一層都會(huì)對(duì)包進(jìn)行封裝,從而形成段、數(shù)數(shù)據(jù)報(bào)、幀,最后是以比特流(二進(jìn)制)進(jìn)行傳輸,到了目標(biāo)主機(jī)后,會(huì)對(duì)每一層又進(jìn)行拆解,從而得到最后的報(bào)文。

http就在最上層,就是應(yīng)用層那里。

http到底離我們多近呢? 甚至于你現(xiàn)在看到的文章,使用的就是http協(xié)議,它還有一個(gè)名字,叫做超文本傳輸協(xié)議,為什么叫超文本呢? 因?yàn)樽铋_(kāi)始的是時(shí)候,http是被用來(lái)傳輸Hypertext文檔的,所以被叫做超文本協(xié)議,當(dāng)然現(xiàn)在可以傳輸其他類(lèi)型的數(shù)據(jù),如: 視頻、音頻、圖片等,但是它依然被稱(chēng)之為超文本協(xié)議。

很難理解吧,沒(méi)關(guān)系,繼續(xù)往下看。

分析http請(qǐng)求報(bào)文和響應(yīng)報(bào)文格式

通過(guò)上面的簡(jiǎn)介,我們知道http是應(yīng)用層協(xié)議,它在網(wǎng)絡(luò)協(xié)議中,是被稱(chēng)之為報(bào)文的,讓我們來(lái)看一下http的請(qǐng)求報(bào)文 和 響應(yīng)報(bào)文吧。

http報(bào)文由4部分組成,分別是起始行、首部行、空白行 以及 實(shí)體組成。以\r\n(也稱(chēng)之為CRLF)進(jìn)行分割。

讓我們來(lái)看一下實(shí)際的報(bào)文呢。

linux中,我們可以使用curl -v 網(wǎng)址來(lái)打印詳細(xì)的請(qǐng)求信息,其中就包括了報(bào)文。

命令:

curl -v http://juejin.cn

請(qǐng)求信息:

基于Python怎么編寫(xiě)一個(gè)簡(jiǎn)單的http服務(wù)器

其中輸出的結(jié)果中> 代表我們發(fā)出的報(bào)文,而< 代表服務(wù)器發(fā)送給我們的響應(yīng)信息。下面我們將結(jié)合報(bào)文來(lái)看上面的數(shù)據(jù)信息。

請(qǐng)求報(bào)文格式如下:

基于Python怎么編寫(xiě)一個(gè)簡(jiǎn)單的http服務(wù)器

其中請(qǐng)求行會(huì)指定http的請(qǐng)求方法,如: GETPOST、HEAD等, URL則是請(qǐng)求的文件路徑,協(xié)議版本需要指定http的版本,最后是以CRLF結(jié)束。

首部行可以有多個(gè),以 (字段名: 值) 的方式出現(xiàn),每一個(gè)首部行同樣是以CRLF結(jié)束。

而后是空行。空行則代表http報(bào)文頭結(jié)束了,接下來(lái)該是發(fā)送的報(bào)文主體了,接下來(lái),我們將上述請(qǐng)求http://juejin.cn的例子,填入表格來(lái)看下:

基于Python怎么編寫(xiě)一個(gè)簡(jiǎn)單的http服務(wù)器

上述是我們使用curl工具請(qǐng)求的http://juejin.cn請(qǐng)求報(bào)文整體形式,我們可以看到,我們使用了GET方法,獲取服務(wù)器的/信息,使用的協(xié)議是HTTP/1.1,而后攜帶了3個(gè)首部行,分別是User-AgentHost以及Accept。

響應(yīng)報(bào)文格式如下:

基于Python怎么編寫(xiě)一個(gè)簡(jiǎn)單的http服務(wù)器

將響應(yīng)報(bào)文和請(qǐng)求報(bào)文進(jìn)行對(duì)比,我們不難發(fā)現(xiàn),除了第一行以外,其他的格式都是一樣的,所以,我們僅介紹響應(yīng)行的信息,在響應(yīng)報(bào)行中,第一個(gè)是協(xié)議的版本,這個(gè)是服務(wù)器的協(xié)議版本,而后便是狀態(tài)碼,用于告知客戶端,服務(wù)器響應(yīng)的信息,最后是短語(yǔ),短語(yǔ)的作用是告知使用者,這個(gè)返回信息大概是什么意思。

好了,我們將上述juejin.cn響應(yīng)給我們的報(bào)文,我們填到表格中呢:

基于Python怎么編寫(xiě)一個(gè)簡(jiǎn)單的http服務(wù)器

上述是我們使用curl請(qǐng)求http://juejin.cn/,服務(wù)器返回的信息,我們逐行來(lái)看下,響應(yīng)行,告知了我們http版本是HTTP/1.1,狀態(tài)碼是301,短語(yǔ)是 鏈接被轉(zhuǎn)移了。

上述我們?nèi)魞H通過(guò)狀態(tài)碼的話,是很難get到整個(gè)報(bào)文的意思的,不過(guò)有短語(yǔ),就可以猜一下了。

首部行,告知了我們服務(wù)器 、時(shí)間 、 報(bào)文類(lèi)型 以及 報(bào)文長(zhǎng)度。還記得我們第一段落介紹過(guò)得,http現(xiàn)在除了發(fā)送超文本以外,還可以發(fā)送圖片、視頻等,就是通過(guò)首部行Content-Type來(lái)確定的。

接著是空白行,最后是報(bào)文主體,哎,有沒(méi)有感覺(jué)奇怪呢?為什么請(qǐng)求報(bào)文主體是空的呢?這是因?yàn)閳?bào)文主體長(zhǎng)度是由首部行Content-Length來(lái)定義的,如上報(bào)文展示的是,我們報(bào)文主體有262個(gè)字符。

手寫(xiě)一個(gè)簡(jiǎn)單的http服務(wù)器

上述,我們介紹了,什么是http以及初略的看了一下 http的請(qǐng)求報(bào)文和響應(yīng)報(bào)文,那么,我們?nèi)绾螛?gòu)建一個(gè)http服務(wù)器呢?

我們知道,http是應(yīng)用層協(xié)議,是基于傳輸層tcp來(lái)實(shí)現(xiàn)的,所以,我們?nèi)粝霕?gòu)建一個(gè)http服務(wù)器,那么應(yīng)該寫(xiě)一個(gè)socket程序出來(lái)吧。

import socket
import threading

def handle(client , addr):
    print("from " , addr)
    data = client.recv(1024)
    for k,v in enumerate(data.decode().split("\r\n")):
        print(k ,v)

def main():
    s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
    s.bind(("127.0.0.1",8080))
    s.listen()
    
    while True:
        client , addr = s.accept() 
        t = threading.Thread(target=handle,args=(client,addr))
        t.start()

if __name__ == '__main__'
    main()

上述,我們寫(xiě)了一個(gè)tcp程序,它將監(jiān)聽(tīng)本地回環(huán)地址的8080端口,若此時(shí)我們使用curl -v 127.0.0.1:8080請(qǐng)求一下該接口,我們將會(huì)得到請(qǐng)求報(bào)文了,如下:

基于Python怎么編寫(xiě)一個(gè)簡(jiǎn)單的http服務(wù)器

我們得到請(qǐng)求報(bào)文后,可以構(gòu)建一個(gè)響應(yīng)報(bào)文發(fā)送回去,例如: Hello, Destined Person.,我們就可以這樣來(lái)構(gòu)建http 請(qǐng)求報(bào)文信息:

import socket
import threading

def handle(client , addr):
    print("from " , addr)
    data = client.recv(1024)
    
    #請(qǐng)求報(bào)文
    for k,v in enumerate(data. decode() .split("\r\n")):
        print(k ,v)
        
    bodyText = "He1lo,Destined Person."
    #響應(yīng)報(bào)文
    #響應(yīng)行
    client.send(b"HTTP/1.1 200 OK\r\n")
    #首部行
    client. send(b"Server: pdudo_web_sites\r\n") 
    client. send(b"Content-Type: text/html\r\n")
    client. send(("Content-Length: %s\r\n" % (len(bodyText) + 2)).encode())
    client. send(b"\r\n")
    client. send(("%s\r\n" %(bodyText)).encode())
    
def main():
    try:
        s = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
        s .bind(("127.0.0.1"8080))
        s .listen()
        
        while True:
            client,addr = s.accept()
            t = threading.Thread(target=handle,args=(client,addr))
            t.start()
    finally:
        s.close()

if __name__ == '__main__':
    main()

最后我們使用curl再來(lái)測(cè)試一下,是可以得到消息的。

基于Python怎么編寫(xiě)一個(gè)簡(jiǎn)單的http服務(wù)器

“基于Python怎么編寫(xiě)一個(gè)簡(jiǎn)單的http服務(wù)器”的內(nèi)容就介紹到這里了,感謝大家的閱讀。如果想了解更多行業(yè)相關(guān)的知識(shí)可以關(guān)注億速云網(wǎng)站,小編將為大家輸出更多高質(zhì)量的實(shí)用文章!

向AI問(wèn)一下細(xì)節(jié)

免責(zé)聲明:本站發(fā)布的內(nèi)容(圖片、視頻和文字)以原創(chuàng)、轉(zhuǎn)載和分享為主,文章觀點(diǎn)不代表本網(wǎng)站立場(chǎng),如果涉及侵權(quán)請(qǐng)聯(lián)系站長(zhǎng)郵箱:is@yisu.com進(jìn)行舉報(bào),并提供相關(guān)證據(jù),一經(jīng)查實(shí),將立刻刪除涉嫌侵權(quán)內(nèi)容。

AI