http
TCP/IPTCPhttp是一个应用层协议,准确的来说是基于TCP/IP
4层网络协议中的传输层中的TCP
应用层协议。
额,4层模型大概是这样的:
在网络通信中,用户的数据是以报文来传输的,但是在实际通信中,每一层都会对包进行封装,从而形成段、数数据报、帧,最后是以比特流(二进制)进行传输,到了目标主机后,会对每一层又进行拆解,从而得到最后的报文。
http
就在最上层,就是应用层那里。
http
到底离我们多近呢? 甚至于你现在看到的文章,使用的就是http
协议,它还有一个名字,叫做超文本传输协议,为什么叫超文本呢? 因为最开始的是时候,http
是被用来传输Hypertext
文档的,所以被叫做超文本协议,当然现在可以传输其他类型的数据,如: 视频、音频、图片等,但是它依然被称之为超文本协议。
很难理解吧,没关系,继续往下看。
通过上面的简介,我们知道http
是应用层协议,它在网络协议中,是被称之为报文的,让我们来看一下http
的请求报文 和 响应报文吧。
http
报文由4部分组成,分别是起始行、首部行、空白行 以及 实体组成。以rn
(也称之为CRLF
)进行分割。
让我们来看一下实际的报文呢。
在linux
中,我们可以使用curl -v 网址
来打印详细的请求信息,其中就包括了报文。
命令:
curl -v http://juejin.cn
请求信息:
其中输出的结果中>
代表我们发出的报文,而<
代表服务器发送给我们的响应信息。下面我们将结合报文来看上面的数据信息。
请求报文格式如下:
其中请求行会指定http
的请求方法,如: GET
、POST
、HEAD
等, URL
则是请求的文件路径,协议版本需要指定http
的版本,最后是以CRLF
结束。
首部行可以有多个,以 (字段名: 值) 的方式出现,每一个首部行同样是以CRLF
结束。
而后是空行。空行则代表http
报文头结束了,接下来该是发送的报文主体了,接下来,我们将上述请求http://juejin.cn
的例子,填入表格来看下:
上述是我们使用curl
工具请求的http://juejin.cn
请求报文整体形式,我们可以看到,我们使用了GET
方法,获取服务器的/
信息,使用的协议是HTTP/1.1
,而后携带了3个首部行,分别是User-Agent
、Host
以及Accept
。
响应报文格式如下:
将响应报文和请求报文进行对比,我们不难发现,除了第一行以外,其他的格式都是一样的,所以,我们仅介绍响应行的信息,在响应报行中,第一个是协议的版本,这个是服务器的协议版本,而后便是状态码,用于告知客户端,服务器响应的信息,最后是短语,短语的作用是告知使用者,这个返回信息大概是什么意思。
好了,我们将上述juejin.cn
响应给我们的报文,我们填到表格中呢:
上述是我们使用curl
请求http://juejin.cn/
,服务器返回的信息,我们逐行来看下,响应行,告知了我们http
版本是HTTP/1.1
,状态码是301
,短语是 链接被转移了。
上述我们若仅通过状态码的话,是很难get
http
httphttp-Protokoll. Es hat auch einen Namen, der Hypertext Transfer Protocol heißt. Da zu Beginn http
Hypertext-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 http
httphttpDie Nachricht besteht aus 4 Teilen, nämlich der Startzeile, der Kopfzeile, der Leerzeile und der Entität. Teilen mit rn
CRLFlinuxcurl -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__ == '__main__' main()
>
< stellt die Antwortinformationen dar, die uns vom Server gesendet wurden. Als nächstes werden wir uns die oben genannten Dateninformationen in Verbindung mit der Nachricht ansehen. #🎜🎜##🎜🎜#Das Format der Anforderungsnachricht lautet wie folgt: #🎜🎜##🎜🎜#http
GET</code >, <code>POST, HEAD
URLhttpCRLF. #🎜🎜##🎜🎜#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< /code> Füllen Sie zum Beispiel das Formular aus und werfen Sie einen Blick darauf: #🎜🎜##🎜🎜#
#🎜🎜##🎜🎜#Das Obige ist die 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.1
User-Agent, Host
Accept. #🎜🎜##🎜🎜#Das Antwortnachrichtenformat ist wie folgt: #🎜🎜##🎜🎜#juejin.cn
#🎜🎜##🎜🎜#Das Obige ist Wir verwenden curl
http://juejin.cn/http< Das /code>-Version ist HTTP/1.1
, der Statuscode ist 301
bekommen, aber mit der Phrase können wir sie erraten. #🎜🎜#首部行,告知了我们服务器 、时间 、 报文类型 以及 报文长度。还记得我们第一段落介绍过得,http
现在除了发送超文本以外,还可以发送图片、视频等,就是通过首部行Content-Type
来确定的。
接着是空白行,最后是报文主体,哎,有没有感觉奇怪呢?为什么请求报文主体是空的呢?这是因为报文主体长度是由首部行Content-Length
来定义的,如上报文展示的是,我们报文主体有262个字符。
上述,我们介绍了,什么是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__ == '__main__' main()
上述,我们写了一个tcp
程序,它将监听本地回环地址的8080
端口,若此时我们使用curl -v 127.0.0.1:8080
请求一下该接口,我们将会得到请求报文了,如下:
我们得到请求报文后,可以构建一个响应报文发送回去,例如: 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__ == '__main__': main()
最后我们使用curl
再来测试一下,是可以得到消息的。
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!