網站首頁 編程語言 正文
靜態Web服務器-返回固定頁面數據
學習目標
能夠寫出組裝固定頁面數據的響應報文
1. 開發自己的靜態Web服務器
實現步驟:
- 編寫一個TCP服務端程序
- 獲取瀏覽器發送的http請求報文數據
- 讀取固定頁面數據,把頁面數據組裝成HTTP響應報文數據發送給瀏覽器。
- HTTP響應報文數據發送完成以后,關閉服務于客戶端的套接字。
2. 靜態Web服務器-返回固定頁面數據的示例代碼
import socket
# 判斷是否是主模塊的代碼
if __name__ == '__main__':
# 創建tcp服務端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 設置端口號復用,程序退出端口號立即釋放
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 綁定端口號
tcp_server_socket.bind(("", 8000))
# 設置監聽
tcp_server_socket.listen(128)
# 循環等待接受客戶端的連接請求
while True:
# 等待接受客戶端的連接請求
new_socket, ip_port = tcp_server_socket.accept()
# 代碼執行到此,說明連接建立成功
# 接收客戶端的請求信息
recv_data = new_socket.recv(4096)
print(recv_data)
# 打開文件讀取文件中的數據
with open("static/index.html", "r") as file: # 這里的file表示打開文件的對象
file_data = file.read()
# 提示: with open 關閉文件這步操作不用程序員來完成,系統幫我們來完成
# 響應行
response_line = "HTTP/1.1 200 OK\r\n"
# 響應頭
response_header = "Server: PWS/1.0\r\n"
# 響應體
response_body = file_data
# 把數據封裝成http 響應報文格式的數據
response = response_line + response_header + "\r\n" + response_body
# 把字符串編碼成二進制
response_data = response.encode("utf-8")
# 發送給瀏覽器的響應報文數據
new_socket.send(response_data)
# 關閉服務于客戶端的套接字
new_socket.close()
3. 小結
編寫一個TCP服務端程序
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 循環接受客戶端的連接請求
while True:
conn_socket, ip_port = tcp_server_socket.accept()
獲取瀏覽器發送的http請求報文數據
client_request_data = conn_socket.recv(4096)
讀取固定頁面數據,把頁面數據組裝成HTTP響應報文數據發送給瀏覽器。
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
conn_socket.send(response_data)
HTTP響應報文數據發送完成以后,關閉服務于客戶端的套接字。
conn_socket.close()
靜態Web服務器-返回指定頁面數據
學習目標
能夠寫出組裝指定頁面數據的響應報文
1. 靜態Web服務器的問題
目前的Web服務器,不管用戶訪問什么頁面,返回的都是固定頁面的數據,接下來需要根據用戶的請求返回指定頁面的數據
返回指定頁面數據的實現步驟:
- 獲取用戶請求資源的路徑
- 根據請求資源的路徑,讀取指定文件的數據
- 組裝指定文件數據的響應報文,發送給瀏覽器
- 判斷請求的文件在服務端不存在,組裝404狀態的響應報文,發送給瀏覽器
2. 靜態Web服務器-返回指定頁面數據的示例代碼
import socket
import os
def main():
# 創建tcp服務端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 設置端口號復用,程序退出端口號立即釋放
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 綁定端口號
tcp_server_socket.bind(("", 8000))
# 設置監聽
tcp_server_socket.listen(128)
# 循環等待接受客戶端的連接請求
while True:
# 等待接受客戶端的連接請求
new_socket, ip_port = tcp_server_socket.accept()
# 代碼執行到此,說明連接建立成功
# 接收客戶端的請求信息
recv_data = new_socket.recv(4096)
# 判斷接收的數據長度是否為0
if len(recv_data) == 0:
new_socket.close()
return
# 對二進制數據進行解碼
recv_content = recv_data.decode("utf-8")
print(recv_content)
# 對數據按照空格進行分割
request_list = recv_content.split(" ", maxsplit=2)
# 獲取請求的資源路徑
request_path = request_list[1]
print(request_path)
# 判斷請求的是否是根目錄,如果是根目錄設置返回的信息
if request_path == "/":
request_path = "/index.html"
# 1. os.path.exits
# os.path.exists("static/" + request_path)
# 2. try-except
# 打開文件讀取文件中的數據, 提示:這里使用rb模式,兼容打開圖片文件
with open("static" + request_path, "rb") as file: # 這里的file表示打開文件的對象
file_data = file.read()
# 提示: with open 關閉文件這步操作不用程序員來完成,系統幫我們來完成
# 代碼執行到此,說明文件存在,返回200狀態信息
# 響應行
response_line = "HTTP/1.1 200 OK\r\n"
# 響應頭
response_header = "Server: PWS/1.0\r\n"
# 響應體
response_body = file_data
# 把數據封裝成http 響應報文格式的數據
response = (response_line +
response_header +
"\r\n").encode("utf-8") + response_body
# 發送給瀏覽器的響應報文數據
new_socket.send(response)
# 關閉服務于客戶端的套接字
new_socket.close()
# 判斷是否是主模塊的代碼
if __name__ == '__main__':
main()
3. 小結
獲取用戶請求資源的路徑
request_list = client_request_conent.split(" ", maxsplit=2)
request_path = request_list[1]
根據請求資源的路徑,讀取請求指定文件的數據
with open("static" + request_path, "rb") as file:
file_data = file.read()
組裝指定文件數據的響應報文,發送給瀏覽器
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
conn_socket.send(response_data)
判斷請求的文件在服務端不存在,組裝404狀態的響應報文,發送給瀏覽器
try:
# 打開指定文件,代碼省略...
except Exception as e:
conn_socket.send(404響應報文數據)
靜態Web服務器-返回404頁面數據
import socket
import os
def main():
# 創建tcp服務端套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 設置端口號復用,程序退出端口號立即釋放
tcp_server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 綁定端口號
tcp_server_socket.bind(("", 8000))
# 設置監聽
tcp_server_socket.listen(128)
# 循環等待接受客戶端的連接請求
while True:
# 等待接受客戶端的連接請求
new_socket, ip_port = tcp_server_socket.accept()
# 代碼執行到此,說明連接建立成功
# 接收客戶端的請求信息
recv_data = new_socket.recv(4096)
# 判斷接收的數據長度是否為0
if len(recv_data) == 0:
new_socket.close()
return
# 對二進制數據進行解碼
recv_content = recv_data.decode("utf-8")
print(recv_content)
# 對數據按照空格進行分割
request_list = recv_content.split(" ", maxsplit=2)
# 獲取請求的資源路徑
request_path = request_list[1]
print(request_path)
# 判斷請求的是否是根目錄,如果是根目錄設置返回的信息
if request_path == "/":
request_path = "/index.html"
# 1. os.path.exits
# os.path.exists("static/" + request_path)
# 2. try-except
try:
# 打開文件讀取文件中的數據, 提示:這里使用rb模式,兼容打開圖片文件
with open("static" + request_path, "rb") as file: # 這里的file表示打開文件的對象
file_data = file.read()
# 提示: with open 關閉文件這步操作不用程序員來完成,系統幫我們來完成
except Exception as e:
# 代碼執行到此,說明沒有請求的該文件,返回404狀態信息
# 響應行
response_line = "HTTP/1.1 404 Not Found\r\n"
# 響應頭
response_header = "Server: PWS/1.0\r\n"
# 讀取404頁面數據
with open("static/error.html", "rb") as file:
file_data = file.read()
# 響應體
response_body = file_data
# 把數據封裝成http 響應報文格式的數據
response = (response_line +
response_header +
"\r\n").encode("utf-8") + response_body
# 發送給瀏覽器的響應報文數據
new_socket.send(response)
else:
# 代碼執行到此,說明文件存在,返回200狀態信息
# 響應行
response_line = "HTTP/1.1 200 OK\r\n"
# 響應頭
response_header = "Server: PWS/1.0\r\n"
# 響應體
response_body = file_data
# 把數據封裝成http 響應報文格式的數據
response = (response_line +
response_header +
"\r\n").encode("utf-8") + response_body
# 發送給瀏覽器的響應報文數據
new_socket.send(response)
finally:
# 關閉服務于客戶端的套接字
new_socket.close()
# 判斷是否是主模塊的代碼
if __name__ == '__main__':
main()
原文鏈接:https://blog.csdn.net/qq_46092061/article/details/121569012
相關推薦
- 2022-11-01 Python正則表達中re模塊的使用_python
- 2022-11-26 Mongodb?如何將時間戳轉換為年月日日期_MongoDB
- 2022-12-23 swift指針及內存管理內存綁定實例詳解_Swift
- 2022-12-19 python的sorted函數及使用解析_python
- 2022-05-01 使用SQL實現車流量的計算的示例代碼_MsSql
- 2022-05-22 vscode調試container中的程序的方法步驟_相關技巧
- 2022-07-30 golang?redis中Pipeline通道的使用詳解_Golang
- 2022-10-18 使用shell腳本快速登錄容器的實現步驟_linux shell
- 最近更新
-
- window11 系統安裝 yarn
- 超詳細win安裝深度學習環境2025年最新版(
- Linux 中運行的top命令 怎么退出?
- MySQL 中decimal 的用法? 存儲小
- get 、set 、toString 方法的使
- @Resource和 @Autowired注解
- Java基礎操作-- 運算符,流程控制 Flo
- 1. Int 和Integer 的區別,Jav
- spring @retryable不生效的一種
- Spring Security之認證信息的處理
- Spring Security之認證過濾器
- Spring Security概述快速入門
- Spring Security之配置體系
- 【SpringBoot】SpringCache
- Spring Security之基于方法配置權
- redisson分布式鎖中waittime的設
- maven:解決release錯誤:Artif
- restTemplate使用總結
- Spring Security之安全異常處理
- MybatisPlus優雅實現加密?
- Spring ioc容器與Bean的生命周期。
- 【探索SpringCloud】服務發現-Nac
- Spring Security之基于HttpR
- Redis 底層數據結構-簡單動態字符串(SD
- arthas操作spring被代理目標對象命令
- Spring中的單例模式應用詳解
- 聊聊消息隊列,發送消息的4種方式
- bootspring第三方資源配置管理
- GIT同步修改后的遠程分支