Heim  >  Artikel  >  Backend-Entwicklung  >  Wie schreibe ich einen einfachen HTTP-Server mit Python?

Wie schreibe ich einen einfachen HTTP-Server mit Python?

王林
王林nach vorne
2023-05-07 22:25:061752Durchsuche

Was ist http

httpTCP/IPTCPhttp是一个应用层协议,准确的来说是基于TCP/IP4层网络协议中的传输层中的TCP应用层协议。

额,4层模型大概是这样的:

Wie schreibe ich einen einfachen HTTP-Server mit Python?

在网络通信中,用户的数据是以报文来传输的,但是在实际通信中,每一层都会对包进行封装,从而形成段、数数据报、帧,最后是以比特流(二进制)进行传输,到了目标主机后,会对每一层又进行拆解,从而得到最后的报文。

http就在最上层,就是应用层那里。

http到底离我们多近呢? 甚至于你现在看到的文章,使用的就是http协议,它还有一个名字,叫做超文本传输协议,为什么叫超文本呢? 因为最开始的是时候,http是被用来传输Hypertext文档的,所以被叫做超文本协议,当然现在可以传输其他类型的数据,如: 视频、音频、图片等,但是它依然被称之为超文本协议。

很难理解吧,没关系,继续往下看。

分析http请求报文和响应报文格式

通过上面的简介,我们知道http是应用层协议,它在网络协议中,是被称之为报文的,让我们来看一下http的请求报文 和 响应报文吧。

http报文由4部分组成,分别是起始行、首部行、空白行 以及 实体组成。以rn(也称之为CRLF)进行分割。

让我们来看一下实际的报文呢。

linux中,我们可以使用curl -v 网址来打印详细的请求信息,其中就包括了报文。

命令:

curl -v http://juejin.cn

请求信息:

Wie schreibe ich einen einfachen HTTP-Server mit Python?

其中输出的结果中> 代表我们发出的报文,而代表服务器发送给我们的响应信息。下面我们将结合报文来看上面的数据信息。

请求报文格式如下:

Wie schreibe ich einen einfachen HTTP-Server mit Python?

其中请求行会指定http的请求方法,如: GETPOSTHEAD等, URL则是请求的文件路径,协议版本需要指定http的版本,最后是以CRLF结束。

首部行可以有多个,以 (字段名: 值) 的方式出现,每一个首部行同样是以CRLF结束。

而后是空行。空行则代表http报文头结束了,接下来该是发送的报文主体了,接下来,我们将上述请求http://juejin.cn的例子,填入表格来看下:

Wie schreibe ich einen einfachen HTTP-Server mit Python?

上述是我们使用curl工具请求的http://juejin.cn请求报文整体形式,我们可以看到,我们使用了GET方法,获取服务器的/信息,使用的协议是HTTP/1.1,而后携带了3个首部行,分别是User-AgentHost以及Accept

响应报文格式如下:

Wie schreibe ich einen einfachen HTTP-Server mit Python?

将响应报文和请求报文进行对比,我们不难发现,除了第一行以外,其他的格式都是一样的,所以,我们仅介绍响应行的信息,在响应报行中,第一个是协议的版本,这个是服务器的协议版本,而后便是状态码,用于告知客户端,服务器响应的信息,最后是短语,短语的作用是告知使用者,这个返回信息大概是什么意思。

好了,我们将上述juejin.cn响应给我们的报文,我们填到表格中呢:

Wie schreibe ich einen einfachen HTTP-Server mit Python?

上述是我们使用curl请求http://juejin.cn/,服务器返回的信息,我们逐行来看下,响应行,告知了我们http版本是HTTP/1.1,状态码是301,短语是 链接被转移了。

上述我们若仅通过状态码的话,是很难get#🎜🎜##🎜🎜#In der Netzwerkkommunikation werden Benutzerdaten in Nachrichten übertragen, in der tatsächlichen Kommunikation jedoch. Jede Schicht wird dies tun Kapseln Sie das Paket, um Segmente, Datagramme und Frames zu bilden, und übertragen Sie es schließlich als Bitstrom (binär). Nach der Ankunft am Zielhost wird jede Schicht zerlegt, um den endgültigen Bericht zu erhalten. #🎜🎜##🎜🎜#httphttphttp-Protokoll. Es hat auch einen Namen, der Hypertext Transfer Protocol heißt. Da zu Beginn httpHypertext-Dokumenten verwendet wurde, wurde es als Hypertext-Protokoll bezeichnet. Natürlich können jetzt auch andere Datentypen übertragen werden, wie zum Beispiel: Video, Audio, Bilder usw., wird aber immer noch als Hypertext-Protokoll bezeichnet. #🎜🎜##🎜🎜# Es ist schwer zu verstehen, es spielt keine Rolle, lesen Sie einfach weiter. #🎜🎜##🎜🎜#Analysieren Sie das HTTP-Anforderungsnachrichten- und Antwortnachrichtenformat #🎜🎜##🎜🎜#Durch die obige Einführung wissen wir, dass httphttphttpDie Nachricht besteht aus 4 Teilen, nämlich der Startzeile, der Kopfzeile, der Leerzeile und der Entität. Teilen mit rnCRLFlinuxcurl -v URLimport 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__ == &#39;__main__&#39; main()#🎜🎜#Informationen anfordern: #🎜🎜##🎜🎜#So schreiben Sie einen einfachen HTTP-Server auf Basis von Python#🎜🎜##🎜🎜#In den Ausgabeergebnissen stellt > #🎜🎜##🎜🎜#Die Anforderungszeile gibt die Anforderungsmethode von <code>httpGET, POST, HEADURLhttpCRLF. #🎜🎜##🎜🎜#Es können mehrere Kopfzeilen vorhanden sein, die in der Form (Feldname: Wert) angezeigt werden. Jede Kopfzeile endet auch mit CRLF. #🎜🎜##🎜🎜#Dann gibt es eine Leerzeile. Eine leere Zeile stellt das Ende des http-Nachrichtenkopfes dar, und der nächste Schritt ist der Text der gesendeten Nachricht. Als nächstes stellen wir die obige Anfrage http://juejin.cn Füllen Sie zum Beispiel das Formular aus und werfen Sie einen Blick darauf: #🎜🎜##🎜🎜#<img src="https://img.php.cn/upload/article/000/465/014/168346951028043.%20png" alt=" So schreiben Sie einen einfachen HTTP-Server basierend auf Python">#🎜🎜##🎜🎜#Das Obige ist die <code>http://juejin.cn-Anfrage, wir verwenden den curl-Tool zum Anfordern Aus der Gesamtform der Nachricht können wir ersehen, dass wir die Methode GET/-Informationen des Servers und das Protokoll abzurufen Verwendet wird HTTP/1.1User-Agent, HostAccept. #🎜🎜##🎜🎜#Das Antwortnachrichtenformat ist wie folgt: #🎜🎜##🎜🎜#So schreiben Sie einen einfachen HTTP-Server auf Basis von Python#🎜🎜##🎜🎜#Wenn wir die Antwortnachricht und die Anforderungsnachricht vergleichen, können wir leicht feststellen, dass es bis auf die erste Zeile andere Formate gibt sind gleich, daher geben wir nur die Informationen der Antwortzeile ein. In der Antwortzeile ist die erste die Protokollversion, die die Protokollversion des Servers ist, und dann gibt es den Statuscode, der verwendet wird Informieren Sie den Client darüber, dass der Server geantwortet hat, und schließlich einen Satz. Die Funktion des Satzes besteht darin, den Benutzer darüber zu informieren, was die zurückgegebenen Informationen wahrscheinlich bedeuten. #🎜🎜##🎜🎜#Okay, füllen wir die obige Nachricht, die uns von juejin.cn#🎜🎜##🎜🎜#Das Obige ist Wir verwenden curlhttp://juejin.cn/http-Version ist <code>HTTP/1.1, der Statuscode ist 301bekommen, aber mit der Phrase können wir sie erraten. #🎜🎜#

首部行,告知了我们服务器 、时间 、 报文类型 以及 报文长度。还记得我们第一段落介绍过得,http现在除了发送超文本以外,还可以发送图片、视频等,就是通过首部行Content-Type来确定的。

接着是空白行,最后是报文主体,哎,有没有感觉奇怪呢?为什么请求报文主体是空的呢?这是因为报文主体长度是由首部行Content-Length来定义的,如上报文展示的是,我们报文主体有262个字符。

手写一个简单的http服务器

上述,我们介绍了,什么是http以及初略的看了一下 http的请求报文和响应报文,那么,我们如何构建一个http服务器呢?

我们知道,http是应用层协议,是基于传输层tcp来实现的,所以,我们若想构建一个http服务器,那么应该写一个socket程序出来吧。

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__ == &#39;__main__&#39;
    main()

上述,我们写了一个tcp程序,它将监听本地回环地址的8080端口,若此时我们使用curl -v 127.0.0.1:8080请求一下该接口,我们将会得到请求报文了,如下:

Wie schreibe ich einen einfachen HTTP-Server mit Python?

我们得到请求报文后,可以构建一个响应报文发送回去,例如: Hello, Destined Person.,我们就可以这样来构建http

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)
        
    bodyText = "He1lo,Destined Person."
    #响应报文
    #响应行
    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__ == &#39;__main__&#39;:
    main()

最后我们使用curl再来测试一下,是可以得到消息的。

Wie schreibe ich einen einfachen HTTP-Server mit Python?

Das obige ist der detaillierte Inhalt vonWie schreibe ich einen einfachen HTTP-Server mit Python?. Für weitere Informationen folgen Sie bitte anderen verwandten Artikeln auf der PHP chinesischen Website!

Stellungnahme:
Dieser Artikel ist reproduziert unter:yisu.com. Bei Verstößen wenden Sie sich bitte an admin@php.cn löschen