HTTP是Hyper Text Transfer Protocol(超文本傳輸協定)的縮寫。它的發展是萬維網協會(World Wide Web Consortium)和Internet工作小組IETF(Internet Engineering Task Force)合作的結果,(他們)最終發布了一系列的RFC,RFC 1945定義了HTTP/1.0版本。其中最著名的就是RFC 2616。 RFC 2616定義了今天普遍使用的一個版本-HTTP 1.1。
HTTP協定(HyperText Transfer Protocol,超文本傳輸協定)是用於從WWW伺服器傳輸超文本到本機瀏覽器的傳送協定。它可以使瀏覽器更加高效,使網路傳輸減少。它不僅保證電腦正確快速地傳輸超文本文檔,還確定傳輸文檔中的哪一部分,以及哪部分內容首先顯示(如文本先於圖形)等。
HTTP是基於TCP/IP通訊協定來傳遞資料(HTML 檔案, 圖片檔案, 查詢結果等)。
HTTP是一個應用層協議,由請求和回應構成,是一個標準的客戶端伺服器模型。
HTTP是一個無狀態的協定。
![Upload 深入理解HTTP協定.jpg failed. Please try again.]
這樣就限制了使用HTTP協議,無法實現在客戶端沒有發起請求的時候,伺服器將訊息推送給客戶端。
HTTP協定是一個無狀態的協議,同一個客戶端的這次請求和上次請求是沒有對應關係。
我們可以跟資料庫的CRUD增刪改查作業對應起來:
CREATE :PUT
Content-Type: text/html
Content-Type指示回應的內容,這裡是text/html表示HTML網頁。
當瀏覽器讀取到新浪首頁的HTML源碼後,它會解析HTML,顯示頁面,然後,根據HTML裡面的各種鏈接,再發送HTTP請求給新浪伺服器,拿到對應的圖片、影片、Flash、JavaScript腳本、CSS等各種資源,最後顯示出完整的頁面。
追蹤了新浪的首頁,我們來總結一下HTTP請求的流程:
方法:GET或POST,GET只要求資源,POST會附帶使用者資料;
路徑:/full/url/path;
網域:由Host頭指定:Host: www.sina.com
以及其他相關的Header;
如果是POST,那麼請求還包括一個Body,包含用戶資料
回應代碼:200表示成功,3xx表示重定向,4xx表示客戶端發送的請求有錯誤,5xx表示伺服器端處理時發生了錯誤;
回應類型:由Content-Type指定;
以及其他相關的Header;
通常伺服器的HTTP回應會攜帶內容,也就是有一個Body,包含回應的內容,網頁的HTML來源碼就在Body中。
Web採用的HTTP協定採用了非常簡單的請求-回應模式,從而大大簡化了開發。當我們編寫一個頁面時,我們只需要在HTTP請求中把HTML發送出去,不需要考慮如何附帶圖片、視頻等,瀏覽器如果需要請求圖片和視頻,它會發送另一個HTTP請求,因此,一個HTTP請求只處理一個資源(此時就可以理解為TCP協定中的短連接,每個連結只獲取一個資源,如需要多個就需要建立多個連結)
HTTP協定同時具備極強的擴展性,雖然瀏覽器請求的是的首頁,但是新浪在HTML中可以鏈入其他伺服器的資源,例如![](http://upload-images.jianshu.io/upload_images/6078268-6060a9b222ef1412.png?imageMogr2/ auto-orient/strip%7CimageView2/2/w/1240),從而將請求壓力分散到各個伺服器上,並且,一個站點可以連結到其他站點,無數個站點互相連結起來,就形成了World Wide Web,簡稱WWW。
HTTP GET請求的格式:
GET /path HTTP/1.1
Header1: Value1
Header2: Value2
Header3: Value3
每個Header一行一個,換行符號是\r \n或用os.linesep
HTTP POST請求的格式:
POST /path HTTP/1.1
Header1: Value1
Header2: Value2
Header3: Value3
當遇到連續兩個\r\n時,Header部分結束,後面的資料全部是Body。
HTTP回應的格式:
200 OK
Header1: Value1
Header2: Value2
Header3: Value3
HTTP回應如果包含body,也是透過\r\n\r\n來分隔的。
請再次注意,Body的資料類型由Content-Type頭來決定,如果是網頁,Body就是文本,如果是圖片,Body就是圖片的二進位資料。
當存在Content-Encoding時,Body資料是被壓縮的,最常見的壓縮方式是gzip,所以,看到Content-Encoding: gzip時,需要將Body資料先解壓縮,才能得到真正的資料。壓縮的目的在於減少Body的大小,加快網路傳輸。
import socketimport multiprocessingimport osimport timedef serverHandler(clientSocket, clientAddr):'与请求的客户端进行交互'# 接收客户端发来的消息 recvData = clientSocket.recv(1024).decode('utf-8') print(recvData)# 服务端向客户端发消息,作为响应 responseLine = 'HTTP/1.1 200 OK' + os.linesep responseHeader = 'Server: laowang' + os.linesep responseHeader += 'Date: %s' % time.ctime() + os.linesep responseBody = '差一点一米八' sendData = (responseLine + responseHeader + os.linesep + responseBody).encode('gbk') clientSocket.send(sendData)# 关闭 clientSocket.close()def main():'程序入口'# socket对象 serverSocket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)# 绑定的端口号,可以重复使用端口号#serverSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)# 绑定 serverSocket.bind(('', 8000))# 监听 serverSocket.listen()while True:# 接收 clientSocket, clientAddr = serverSocket.accept() print(clientSocket)# 开一个新的进程,执行交互 multiprocessing.Process(target=serverHandler, args=(clientSocket, clientAddr)).start()# 关闭客户端对象 clientSocket.close()if __name__ == '__main__': main()
import time,multiprocessing,socket,os,re G_PATH = './html' def serveHandler(clientSocket,clientAddr): recvData = clientSocket.recv(1024).decode('gbk') lineFirst = recvData.splitlines()[0] strFirst = re.split(r' +',lineFirst) fileName = strFirst[1] filePath = G_PATHif '/'== fileName: filePath += './index.html'else: filePath += fileNametry:file = Nonefile =open(filePath,'r',encoding='gbk') responseBody = file.read() responseLine = 'HTTP/1.1 200 OK' + os.linesep responseHeader = 'Server: ererbai' + os.linesep responseHeader += 'Date:%s' % time.ctime() + os.linesep except FileNotFoundError: responseLine = 'HTTP/1.1 404 NOT FOUND' + os.linesep responseHeader = 'Server: ererbai' + os.linesep responseHeader += 'Date:%s' % time.ctime() + os.linesep responseBody = '很抱歉,服务器中找不到你想要的内容' except Exception: responseLine = 'HTTP/1.1 500 ERROR' + os.linesep responseHeader = 'Server: ererbai' + os.linesep responseHeader += 'Date: %s' % time.ctime() + os.linesep responseBody = '服务器正在维护中,请稍后再试。'finally:if file!=None and not file.closed:file.close() senData = (responseLine + responseHeader + os.linesep + responseBody).encode('gbk') clientSocket.send(senData) clientSocket.close() def main(): serveSocket=socket.socket(socket.AF_INET,socket.SOCK_STREAM) serveSocket.bind(('',8000)) serveSocket.listen()while True: clientSocket,clientAddr = serveSocket.accept() print(clientSocket) multiprocessing.Process(target=serveHandler,args=(clientSocket,clientAddr)).start() clientSocket.close()if __name__ == '__main__': main()
學習過程中遇到什麼問題或想取得學習資源的話,歡迎加入學習交流群組
343599877,我們一起學習前端!
以上是web伺服器的具體介紹的詳細內容。更多資訊請關注PHP中文網其他相關文章!