Socket之靜態http服務器編程
- 創建socket套接字
- 綁定端口號
- 設置監聽
- 等待客戶端連接請求
- 封裝http響應報文格式
- 使用客戶端的套接字回覆消息
- 關閉客戶端連接
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(("", 8001))
# 設置監聽
tcp_server_socket.listen(128)
while True:
# 等待接受客戶端的連接請求
new_socket, ip_port = tcp_server_socket.accept()
# 代碼執行到此,說明連接建立成功
recv_client_data = new_socket.recv(4096)
# 對二進制數據進行解碼
recv_client_content = recv_client_data.decode("utf-8")
print(recv_client_content)
with open("static/index.html", "rb") as file:
# 讀取文件數據
file_data = file.read()
# 響應行
response_line = "HTTP/1.1 200 OK\r\n"
# 響應頭
response_header = "Server: Python-server\r\n"
# 響應體
response_body = file_data
# 拼接響應報文
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
# 發送數據
new_socket.send(response_data)
# 關閉服務與客戶端的套接字
new_socket.close()
計算機網絡基礎知識介紹:
HTTP協議介紹
超文本傳輸協議(HTTP,HyperText Transfer Protocol)是互聯網上應用最爲廣泛的一種網絡協議。所有的www文件都必須遵守這個標準。
1、HTTP 協議包括哪些請求?
GET:請求讀取由URL所標誌的信息。
POST:給服務器添加信息(如註釋)。
PUT:在給定的URL下存儲一個文檔。
DELETE:刪除給定的URL所標誌的資源。
2、HTTP 中, POST 與 GET 的區別
1)Get是從服務器上獲取數據,Post是向服務器傳送數據。
2)Get是把參數數據隊列加到提交表單的Action屬性所指向的URL中,值和表單內各個字段一一對應,在URL中可以看到。
3)Get傳送的數據量小,不能大於2KB;Post傳送的數據量較大,一般被默認爲不受限制。
4)根據HTTP規範,GET用於信息獲取,而且應該是安全的和冪等的。
I. 所謂 安全的 意味着該操作用於獲取信息而非修改信息。換句話說,GET請求一般不應產生副作用。就是說,它僅僅是獲取資源信息,就像數據庫查詢一樣,不會修改,增加數據,不會影響資源的狀態。
II. 冪等 的意味着對同一URL的多個請求應該返回同樣的結果。
3、get請求報文
組成:
- 請求行
- 請求頭
- 空行
原始報文:(每行末尾都有一個 ‘\r\n’)
GET / HTTP/1.1 \r\n
Host: localhost:8001\r\n
Connection: keep-alive\r\n
Upgrade-Insecure-Requests: 1\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36\r\n
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8\r\n
Accept-Encoding: gzip, deflate\r\n
Accept-Language: zh-CN,zh;q=0.9\r\n
Cookie: pgv_pvi=1246921728; \r\n
\r\n (請求頭信息後面還有一個單獨的’\r\n’不能省略)
- 請求行
GET / HTTP/1.1 \r\n
分別代表:請求方式、資源路徑、http協議版本 - 請求頭
每一行都是一個鍵值對+\r\n
組成
鍵 | 值 | 說明 |
---|---|---|
Host | localhost:8001 | 服務器的主機地址和端口號,默認是80 |
Connection | keep-alive | 和服務端保持長連接 |
Upgrade-Insecure-Requests | 1 | 讓瀏覽器升級不安全請求,使用https請求 |
User-Agent | Mozilla/5.0… | 用戶代理,也就是客戶端的名稱 |
Accept | text/html, application/xhtml+xml,application/xml;… | 可接受的數據類型 |
Accept-Encoding | gzip, deflate | 可接受的壓縮格式 |
Accept-Language | zh-CN,zh;q=0.9 | 可接受的語言,q代表權值 |
Cookie | pgv_pvi=1246921728; | 登錄用戶的身份標識 |
- 空行
最後要有一個空行\r\n
4、post請求報文
組成:
- 請求行
- 請求頭
- 空行
- 請求體
原始報文:(每行末尾都有一個 ‘\r\n’)
POST /adduser HTTP/1.1\r\n
Host: localhost:8001\r\n
Connection: keep-alive\r\n
Content-Type: application/x-www-form-urlencoded\r\n
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/80.0.3987.87 Safari/537.36\r\n
\r\n(請求頭信息後面還有一個單獨的’\r\n’不能省略)
// Form Data
username=hello&pass=hello
- 請求行
POST /adduser HTTP/1.1\r\n
分別代表:請求方式、資源路徑、http協議版本 - 請求頭
每一行都是一個鍵值對+\r\n
組成,其它參數同get請求
鍵 | 值 | 說明 |
---|---|---|
Content-Type | application/x-www-form-urlencoded | 告訴服務端請求的數據類型 |
-
空行
與請求體之間要有一個空行\r\n
-
請求體
表單默認的數據格式:username=hello&pass=hello
5、響應報文
組成:
- 響應行
- 響應頭
- 空行
- 響應體
原始報文:(每行末尾都有一個 ‘\r\n’)
---響應頭----
HTTP/1.1 200 OK\r\n
---響應行----
Server: apache\r\n
Content-Type: text/html; charset=UTF-8\r\n
Transfer-Encoding: chunked\r\n
Connection: keep-alive\r\n
Date: Sun, 28 Jun 2020 09:01:10 GMT\r\n
---空行----
\r\n(響應頭信息後面還有一個單獨的’\r\n’不能省略)
---響應體----
<!DOCTYPE html><html lang=“en”> …</html>
- 響應行
HTTP/1.1 200 OK\r\n
分別代表:HTTP協議版本、狀態碼、狀態描述 - 響應頭
每一行都是一個鍵值對+\r\n
組成
鍵 | 值 | 說明 |
---|---|---|
Server | apache | 服務器名稱 |
Content-Type | text/html; charset=UTF-8 | 內容類型 |
Transfer-Encoding | chunked | 發送結束的標記是0\r\n, Content-Length表示服務端確定發送給客戶端的內容大小,但是二者只能用其一。 |
Connection | keep-alive | 和客戶端保持長連接 |
Date | Sun, 28 Jun 2020 09:01:10 GMT | 服務端的響應時間 |
-
空行
與請求體之間要有一個空行\r\n
-
響應體
<!DOCTYPE html><html lang=“en”> …</html>
響應給客戶端的數據
三種報文對比
其它請求體內容格式詳見:
6、Connection參數,長、短連接
我們知道HTTP協議採用“請求-應答”模式,當使用普通模式,即非KeepAlive模式時,每個請求/應答客戶和服務器都要新建一個連接,完成之後立即斷開連接(HTTP協議爲無連接的協議);當使用Keep-Alive模式(又稱持久連接、連接重用)時,Keep-Alive功能使客戶端到服務器端的連接持續有效,當出現對服務器的後續請求時,Keep-Alive功能避免了建立或者重新建立連接。
如上圖中,左邊的是關閉Keep-Alive的情況,每次請求都需要建立連接,然後關閉連接;右邊的則是Keep-Alive,在第一次建立請求之後保持連接,然後後續的就不需要每次都建立、關閉連接了, 啓用Keep-Alive模式肯定更高效,性能更高,因爲避免了建立/釋放連接的開銷 。
http 1.0中默認是關閉的,需要在http頭加入"Connection: Keep-Alive",才能啓用Keep-Alive;http 1.1中默認啓用Keep-Alive,如果加入"Connection: close ",才關閉。目前大部分瀏覽器都是用http1.1協議,也就是說默認都會發起Keep-Alive的連接請求了,所以是否能完成一個完整的Keep- Alive連接就看服務器設置情況。
7、常見http狀態碼
HTTP 狀態碼是用於表示web服務器響應狀態的3位數字代碼。
狀態碼 | 說明 |
---|---|
200 | 請求成功 |
307 | 重定向 |
400 | 錯誤的請求,請求地址或者參數有誤 |
404 | 請求資源在服務器不存在 |
500 | 服務器內部源代碼出現錯誤 |