衆所周知,Http協議是基於Tcp協議的基礎上產生的瀏覽器到服務器的通訊協議 ,其根本原理也是經過socket進行通訊。html
使用HTTP協議通訊,須要注意其返回的響應報文格式不能有任何問題。瀏覽器
響應報文,一共包括4個部分,分別是響應行,響應頭,空行,響應體,而且每項數據之間必須使用/r/n隔開。服務器
空行是區分響應頭和響應體的必要數據,不能省略。socket
HTTP靜態Web服務器主要開發思路以下:spa
1.導入socket模塊code
2.建立socket對象server
3.設置端口複用,解決端口阻塞問題htm
4.綁定端口及ip,在綁定端口及IP後,客戶端只能經過綁定的IP及端口給服務器發送請求報文。對象
5.設置監聽,blog
注意:設置監聽成功後,原socket變成被動套接字,不可以進行數據的收發。
6.等待客戶端(瀏覽器)連接(發送請求)
7.使用連接成功後返回的新socket進行數據的收發。
注意:此處返回數據應爲HTTP響應報文。
1 # 1.導入模塊 2 import socket 3 4 5 def main(): 6 # 2.建立socket對象 7 server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM) 9 # 3.設置端口複用 10 server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True) 11 # 4.綁定端口 12 server_socket.bind(('', 8001)) 13 # 5.設置監聽 14 server_socket.listen(128) 15 # 設置循環接收客戶端鏈接,實現多客戶端鏈接 16 while True: 17 # 6.接收客戶端鏈接 18 client_socket, ip_port = server_socket.accept() 19 print("客戶端:%s 上線了,使用端口爲:%s" % ip_port) 20 # 7.接收數據 21 recv_data = client_socket.recv(1024).decode('utf-8') 22 if recv_data: 23 # print('接收的數據爲:', recv_data) 24 # 獲取http請求報文中的指定路徑 25 # split()方法不指定參數時,默認以空白字符(\t,\n,空格)分割 26 # 獲取到的路徑信息分割後,會造成三部分存放到列表中 27 # 1.請求提交的方式:GET/POST 28 # 2.請求路徑信息及參數信息 29 # 3.HTTP協議及版本 30 page_recv_data = recv_data.split()[1] 31 print('請求的資源路徑爲:', page_recv_data) 32 # 判斷接受到的路徑信息是否包含參數 33 # HTTP協議中,參數格式爲:/index.html?name=666&age=12 34 if '?' in page_recv_data: 35 real_recv_page = page_recv_data.split('?')[0] 36 else: 37 real_recv_page = page_recv_data 38 try: 39 # 8.發送數據 40 41 # 接收指定的路徑信息,並讀取文件信息 42 # 注意f-string只能在3.6及以上版本使用 43 data = f'static{real_recv_page}' 44 print(data) 45 with open(data, 'rb') as file: 46 page_data = file.read() 47 except Exception as e: 48 # 8.1 當文件不存在時,編寫HTTP協議以下格式: 49 http_line = 'HTTP/1.1 / 404 NOT FOUND\r\n' 50 http_header = 'Server: PWS/1.0\r\n' 51 http_body = '<h1>Page Not Found!</h1>' 52 send_data = (http_line + http_header + '\r\n' + http_body).encode() 53 client_socket.send(send_data) 54 else: 55 # 8.1 當文件存在時,編寫HTTP協議以下格式: 56 http_line = 'HTTP/1.1 / 200 ok\r\n' 57 http_header = 'Server: PWS/1.0\r\n' 58 send_data = (http_line + http_header + '\r\n').encode() + page_data 59 client_socket.send(send_data) 60 finally: 61 # 斷開與客戶端鏈接 62 client_socket.close() 63 else: 64 print('客戶端:%s,端口號:%s 下線了' % ip_port) 65 break 66 67 # 9.關閉套接字 68 # 關閉服務器 69 # server_socket.close() 70 71 72 # 入口 73 if __name__ == '__main__': 74 main()