手動實現一個簡單的 HTTP 請求

本文我們通過 Socket,寫一個 HTTP 協議,直觀的感受一下上篇文章中的請求和響應。

定義 socket server

通過上篇文章,我們知道 HTTP 協議底層是通過 Socket 實現的,所以我們先通過 socket 定義一個 server


import socket#初始化 socke
sock=socket.socket()
#綁定 地址
sock.bind(('127.0.0.1',8081))#在 sock.listen(5) 中,參數 5 表示最多可以排隊等待處理的連接數量為 5。
# 如果有更多的連接請求到達,超過該數量的連接將被拒絕。
sock.listen(5)
while True:#接受客戶端請求conn,addr=sock.accept()data=conn.recv(1024)print('客戶端的請求數據\r\n',data.decode('utf-8'))print("打印完畢=====")#響應客戶端的請求conn.send(b'Hello world')conn.close()

在 PyCharm 中執行這段代碼后,通過瀏覽器訪問 http://127.0.0.1:8081/
Sever 端 PyCharm 打印結果

客戶端的請求數據
GET / HTTP/1.1
Host: 127.0.0.1:8081
Connection: keep-alive
sec-ch-ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7打印完畢=====

分析客戶端請求參數-GET請求

在上篇文章中我們講到 HTTP 協議在發送請求的時候,必須要包含請求行、請求頭、請求體。這是瀏覽器幫我們組織好的。
此處的請求行為

GET / HTTP/1.1

請求頭為:

Host: 127.0.0.1:8081
Connection: keep-alive
sec-ch-ua: "Chromium";v="122", "Not(A:Brand";v="24", "Google Chrome";v="122"
sec-ch-ua-mobile: ?0
sec-ch-ua-platform: "macOS"
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_15_7) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/122.0.0.0 Safari/537.36
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7
Sec-Fetch-Site: none
Sec-Fetch-Mode: navigate
Sec-Fetch-User: ?1
Sec-Fetch-Dest: document
Accept-Encoding: gzip, deflate, br, zstd
Accept-Language: en-US,en;q=0.9,zh-CN;q=0.8,zh;q=0.7

請求體為:


之所以為空,是因為 GET 請求沒有請求體。

分析客戶端請求參數-PUT請求

首先通過 python request 包發送 put 請求,因為請求必須要包括請求行、請求頭以及請求體,所以 python request 模板會幫我們組織好。

import requestsdata={"username":"test","password":"<PASSWORD>"}
respone=requests.post("http://127.0.0.1:8081",json=data)
print(respone)

Sever 端 PyCharm打印結果

客戶端的請求數據
POST / HTTP/1.1
Host: 127.0.0.1:8081
User-Agent: python-requests/2.31.0
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Content-Length: 46
Content-Type: application/json{"username": "test", "password": "<PASSWORD>"}
打印完畢=====

此處的請求行為:

POST / HTTP/1.1

請求頭為:

Host: 127.0.0.1:8081
User-Agent: python-requests/2.31.0
Accept-Encoding: gzip, deflate, br, zstd
Accept: */*
Connection: keep-alive
Content-Length: 46
Content-Type: application/json

請求體為:

{"username": "test", "password": "<PASSWORD>"}

服務端響應參數

通過瀏覽器訪問 http://127.0.0.1:8081/ 時,雖然 server 端接受到請求了,也給瀏覽器反回了 hello world 但瀏覽器仍然報錯了

另外當我們通過 python request 發送 put 請求時,同樣 server 端接受到請求了,也返回了 hello world 但 request 程序仍然報錯了

Traceback (most recent call last):File "/Users/isx/opt/anaconda3/lib/python3.11/site-packages/urllib3/connectionpool.py", line 791, in urlopenresponse = self._make_request(^^^^^^^^^^^^^^^^^^^File "/Users/isx/opt/anaconda3/lib/python3.11/site-packages/urllib3/connectionpool.py", line 537, in _make_requestresponse = conn.getresponse()^^^^^^^^^^^^^^^^^^File "/Users/isx/opt/anaconda3/lib/python3.11/site-packages/urllib3/connection.py", line 461, in getresponsehttplib_response = super().getresponse()^^^^^^^^^^^^^^^^^^^^^File "/Users/isx/opt/anaconda3/lib/python3.11/http/client.py", line 1390, in getresponseresponse.begin()File "/Users/isx/opt/anaconda3/lib/python3.11/http/client.py", line 325, in beginversion, status, reason = self._read_status()^^^^^^^^^^^^^^^^^^^File "/Users/isx/opt/anaconda3/lib/python3.11/http/client.py", line 307, in _read_statusraise BadStatusLine(line)
http.client.BadStatusLine: Hello world

這是為什么?
上篇文章中,我們也講過,服務端的響應也必須要包括響應行、響應頭以及響應體,而我們寫的 sever 中代碼,趙括響應體,所以瀏覽器和 python request 包會報錯。

#響應客戶端的請求
conn.send(b'Hello world') 

我們遵循服務端的響應也必須要包括響應行、響應頭以及響應體這個要求,改進 server 代碼

import socketsock=socket.socket()sock.bind(('127.0.0.1',8081))
#在 sock.listen(5) 中,參數 5 表示最多可以排隊等待處理的連接數量為 5。
# 如果有更多的連接請求到達,超過該數量的連接將被拒絕。
sock.listen(5)
while True:conn,addr=sock.accept()data=conn.recv(1024)print('客戶端的請求數據\r\n',data.decode('utf-8'))print("打印完畢=====")conn.send(b'HTTP/1.1 200 OK \r\nDate: Tue, 02 Mar 2024 12:00:00 GMT\r\nServer: Apache/2.4.6 (CentOS) OpenSSL/1.0.2k-fips\r\nContent-Type: text/plain\r\nHello world')conn.close()

擴展

content-type

content-type 是請求頭以及響應頭中最重要的參數,它可以分別告訴客戶端和服務端該如何處理請求體或者響應體中的參數。舉個例子:
server代碼

import socketsock=socket.socket()sock.bind(('127.0.0.1',8081))
#在 sock.listen(5) 中,參數 5 表示最多可以排隊等待處理的連接數量為 5。
# 如果有更多的連接請求到達,超過該數量的連接將被拒絕。
sock.listen(5)
while True:conn,addr=sock.accept()data=conn.recv(1024)print('客戶端的請求數據\r\n',data.decode('utf-8'))print("打印完畢=====")conn.send(b'HTTP/1.1 200 OK\r\nContent-Type: text/plain\r\n\r\n{"username": "test", "password": "<PASSWORD>"}')conn.close()

為了更好的呈現響應的結果,這個我們借助 postman 工具。當 Content-Type: text/plain,postman 接受服務端返回的數據類型為 text

當 Content-Type:application/json 時,postman 服務端返回的數據類型為 json

本文來自互聯網用戶投稿,該文觀點僅代表作者本人,不代表本站立場。本站僅提供信息存儲空間服務,不擁有所有權,不承擔相關法律責任。
如若轉載,請注明出處:http://www.pswp.cn/news/715453.shtml
繁體地址,請注明出處:http://hk.pswp.cn/news/715453.shtml
英文地址,請注明出處:http://en.pswp.cn/news/715453.shtml

如若內容造成侵權/違法違規/事實不符,請聯系多彩編程網進行投訴反饋email:809451989@qq.com,一經查實,立即刪除!

相關文章

復試PAT乙級day34

1111~1115 1113 很難&#xff0c;看了題解 人類習慣用 10 進制&#xff0c;可能因為大多數人類有 10 根手指頭&#xff0c;可以用于計數。這個世界上有一種叫“錢串子”&#xff08;學名“蚰蜒”&#xff09;的生物&#xff0c;有 30 只細長的手/腳&#xff0c;在它們的世界里…

【探索AI】十六 深度學習之第2周:深度神經網絡(五)實踐與應用

實踐與應用 實現步驟 當您想要使用深度學習框架構建簡單的深度神經網絡并進行訓練與評估時&#xff0c;您可以按照以下步驟進行操作&#xff1a; 步驟一&#xff1a;選擇深度學習框架 選擇您熟悉或希望學習的深度學習框架&#xff0c;比如TensorFlow、PyTorch、Keras等。 …

算法題目跟連系列之“手把手刷鏈表”

第一道 題目&#xff1a;https://leetcode.cn/problems/partition-list/description/ 86 Partition List 這個題解決的時候&#xff0c;無非就是把鏈表中小于X的元素摘出來形成一個鏈表&#xff0c;同時也把大于等于X的元素摘出來形成另外一個鏈表。最后把這兩個鏈表合并。這個…

卷積神經網絡介紹

卷積神經網絡(Convolutional Neural Networks&#xff0c;CNN) 網絡的組件&#xff1a;卷積層&#xff0c;池化層&#xff0c;激活層和全連接層。 CNN主要由以下層構造而成&#xff1a; 卷積層&#xff1a;Convolutional layer&#xff08;CONV&#xff09;池化層&#xff1a…

docker報錯 fatal error: runtim: out of memory

fatal error: runtim: out of memory 真無語了 系統內存也夠用 原來是虛擬機的不夠用了 &#xff08;原本1g已經加到2g還是會報錯&#xff09; 直接3臺虛擬機都加到4g

多線程(進階四:線程安全的集合類)

目錄 一、多線程環境使用ArrayList 二、多線程環境使用隊列 三、多線程環境使用哈希表 1、HashMap 2、Hashtable 3、ConcurrentHashMap (1)縮小了鎖的粒度 (2)充分使用了CAS原子操作&#xff0c;減少一些加鎖 (3)針對擴容操作的一些優化&#xff08;化整為零&#xff…

maven 項目的創建入門

拓展閱讀 maven 包管理平臺-01-maven 入門介紹 Maven、Gradle、Ant、Ivy、Bazel 和 SBT 的詳細對比表格 maven 包管理平臺-02-windows 安裝配置 mac 安裝配置 maven 包管理平臺-03-maven project maven 項目的創建入門 maven 包管理平臺-04-maven archetype 項目原型 ma…

藍橋杯Python B組練習——python復習2

藍橋杯Python B組練習——python復習2 一、簡介 復習python&#xff0c;參考書《Python編程從入門到實踐》&#xff0c;[美]Eric Mathes著。前一部分見專欄——藍橋杯Python B組練習 這一部分不全&#xff0c;不想寫了 二、字典 1.一個簡單的字典 來看一個游戲&#xff0…

LeetCode -55 跳躍游戲

LeetCode -55 跳躍游戲 給你一個非負整數數組 nums &#xff0c;你最初位于數組的 第一個下標 。數組中的每個元素代表你在該位置可以跳躍的最大長度。 判斷你是否能夠到達最后一個下標&#xff0c;如果可以&#xff0c;返回 true &#xff1b;否則&#xff0c;返回 false 。…

模擬服務器響應的測試框架:moco

第1章&#xff1a;引言 大家好&#xff0c;我是小黑&#xff0c;在這篇博客中&#xff0c;咱們要聊聊Moco測試框架。這個框架&#xff0c;可不是一般的小伙伴&#xff0c;它在模擬服務器響應這塊兒&#xff0c;可是有不少看家本領。 首先&#xff0c;Moco是啥呢&#xff1f;簡…

stable diffusion webUI之賽博菩薩【秋葉】——工具包新手安裝與使用教程

stable diffusion webUI之賽博菩薩【秋葉】——工具包新手安裝與使用教程 AI浪潮襲來&#xff0c;還是學習學習為妙賽博菩薩【秋葉】簡介——&#xff08;葉ye&#xff0c;四聲&#xff0c;同葉&#xff09;A繪世啟動器.exe&#xff08;sd-webui-aki-v4.6.x&#xff09;工具包安…

【面試題解析--Java基礎】回顧與加深,淺淺回顧JAVA常規八股,利用起碎片化時間。

一、Java基礎 1. final 關鍵字的作用&#xff1a; 修飾類時&#xff0c;被修飾的類無法被繼承。修飾方法時&#xff0c;被修飾的方法無法被重寫。修飾變量時&#xff0c;變量為常量&#xff0c;初始化后無法重新賦值。 2. static 關鍵字的作用&#xff1a; 修飾變量和方法時…

住房貸款利息退稅筆記

應該繳稅了才能退稅&#xff0c;如果是學生&#xff0c;沒有繳稅應該是無法退稅的。 產權證明 如果是商品房&#xff0c;沒有取得房產證&#xff0c;那就是房屋預售合同 扣除年度 應選擇上一年 扣除比例 沒有結婚&#xff0c;選否 申報方式

unity 數學 如何計算線和平面的交點

已知一個平面上的一點P0和法向量n&#xff0c;一條直線上的點L0和方向L,求該直線與該平面的交點P 如下圖 首先我們要知道向量歸一化點乘之后得到就是兩個向量的夾角的余弦值&#xff0c;如果兩個向量相互垂直則值是0&#xff0c;小于0則兩個向量的夾角大于90度&#xff0c;大于…

(C語言)函數詳解上

&#xff08;C語言&#xff09;函數詳解上 目錄&#xff1a; 1. 函數的概念 2. 庫函數 2.1 標準庫和頭文件 2.2 庫函數的使用方法 2.2.1 sqrt 功能 2.2.2 頭文件包含 2.2.3 實踐 2.2.4 庫函數文檔的一般格式 3. 自定義函數 3.1 函數的語法形式 3.2 函數的舉例 4. 形參和實參 4.…

MySQL-CDC 新增同步表確無法捕獲增量問題處理

Flink-CDC版本&#xff1a;2.3.0 問題描述 之前通過Flink-CDC捕獲Mysql數據庫的數據變更情況&#xff0c;代碼大致如下&#xff1a; StreamExecutionEnvironment env StreamExecutionEnvironment.getExecutionEnvironment(flinkEnvConf);MySqlSource<String> mysql …

Redis--事務機制的詳解及應用

Redis事務的概念&#xff1a; Redis事務就是將一系列命令包裝成一個隊列&#xff0c;在執行時候按照添加的順序依次執行&#xff0c;中間不會被打斷或者干擾&#xff0c;在執行事務中&#xff0c;其他客戶端提交的命令不可以插入到執行事務的隊列中&#xff0c;簡單來說Redis事…

【Linux】進程優先級以及Linux內核進程調度隊列的簡要介紹

進程優先級 基本概念查看系統進程修改進程的優先級Linux2.6內核進程調度隊列的簡要介紹和進程優先級有關的概念進程切換 基本概念 為什么會存在進程優先級&#xff1f; ??進程優先級用于確定在資源競爭的情況下&#xff0c;哪個進程將被操作系統調度為下一個運行的進程。進程…

SSH教程

ssh 是遠程連接的利器, 可以說凡是涉及到 linux 服務器, ssh 就是一個繞不開的話題. 本文作為一個教程, 盡可能詳細的幫助讀者設置 ssh, 并給出一些常用的 ssh 配置方法 (主要用于 linux 系統的遠程登錄和文件傳輸). 1. 簡介 ssh 分為兩個部分, sshd 服務端和 ssh 客戶端. ssh…

黑馬鴻蒙學習筆記1:TEXT組件

業余時間學習下黑馬鴻蒙課程&#xff0c;主要截取重要的PPT學習&#xff1a; 其實就是用$r&#xff08;&#xff09;的方法&#xff0c;去調用本地化資源文件&#xff0c;可以做多語言了。 比如每個語言目錄下都有個string.json文件&#xff0c;然后用鍵值對name,value的方式搭…