日韩性视频-久久久蜜桃-www中文字幕-在线中文字幕av-亚洲欧美一区二区三区四区-撸久久-香蕉视频一区-久久无码精品丰满人妻-国产高潮av-激情福利社-日韩av网址大全-国产精品久久999-日本五十路在线-性欧美在线-久久99精品波多结衣一区-男女午夜免费视频-黑人极品ⅴideos精品欧美棵-人人妻人人澡人人爽精品欧美一区-日韩一区在线看-欧美a级在线免费观看

歡迎訪問 生活随笔!

生活随笔

當(dāng)前位置: 首頁 > 编程语言 > python >内容正文

python

python客户端软件开发_用 Python 实现一个简易版 HTTP 客户端

發(fā)布時間:2023/12/20 python 37 豆豆
生活随笔 收集整理的這篇文章主要介紹了 python客户端软件开发_用 Python 实现一个简易版 HTTP 客户端 小編覺得挺不錯的,現(xiàn)在分享給大家,幫大家做個參考.

此文為《用 Python 擼一個 Web 服務(wù)器》系列教程的一個補充,這個系列教程介紹了如何使用 Python 內(nèi)置的 socket 庫實現(xiàn)一個簡易版的 Web 服務(wù)器。

之所以寫這篇文章,是因為我發(fā)現(xiàn)很多人并不清楚 HTTP 客戶端的概念,以為只有瀏覽器才叫 HTTP 客戶端。事實上并非如此,我們在 Web 開發(fā)中常見的 Postman、爬蟲程序、curl 命令行工具 等,這些都可以稱為 HTTP 客戶端。

服務(wù)器程序示例

這里以一個 Hello World 程序來作為示例服務(wù)器,實現(xiàn)如下:# server.py

import socket

import threading

def process_connection(client):

"""處理客戶端連接"""

# 接收客戶端發(fā)來的數(shù)據(jù)

data = b''

while True:

chunk = client.recv(1024)

data += chunk

if len(chunk) < 1024:

break

# 打印從客戶端接收的數(shù)據(jù)

print(f'data: {data}')

# 給客戶端發(fā)送響應(yīng)數(shù)據(jù)

client.sendall(b'HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n

Hello World

')

# 關(guān)閉客戶端連接對象

client.close()

def main():

# 創(chuàng)建 socket 對象

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 允許端口復(fù)用

sock.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

# 綁定 IP 和端口

sock.bind(('127.0.0.1', 8000))

# 開始監(jiān)聽

sock.listen(5)

while True:

# 等待客戶端請求

client, addr = sock.accept()

print(f'client type: {type(client)}\naddr: {addr}')

# 創(chuàng)建新的線程來處理客戶端連接

t = threading.Thread(target=process_connection, args=(client,))

t.start()

if __name__ == '__main__':

main()

極簡客戶端

知道了如何用 socket 庫實現(xiàn)服務(wù)器端程序,那么理解客戶端程序的實現(xiàn)就非常容易了。客戶端程序代碼實現(xiàn)如下:# client.py

import socket

# 創(chuàng)建 socket 對象

sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 指定服務(wù)器 IP 和端口,進行連接

sock.connect(('127.0.0.1', 8000))

# 向 URL "/" 發(fā)送 GET 請求

sock.send(b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8000\r\n\r\n')

# 接收服務(wù)端響應(yīng)數(shù)據(jù)

data = b''

while True:

chunk = sock.recv(1024)

data += chunk

if len(chunk) < 1024:

break

# 打印響應(yīng)數(shù)據(jù)

print(data)

# 關(guān)閉連接

sock.close()

相對來說客戶端程序要簡單一些,創(chuàng)建 socket 對象的代碼與服務(wù)器端程序并無差別,客戶端 socket 對象根據(jù) IP 和端口來連接指定的服務(wù)器,建立好連接后就可以發(fā)送數(shù)據(jù)了,這里根據(jù) HTTP 協(xié)議構(gòu)造了一個針對 / URL 路徑的 GET 請求,為了簡單起見,請求頭中僅攜帶了 HTTP 協(xié)議規(guī)定的必傳字段 Host,請求發(fā)送成功后便可以接收服務(wù)器端響應(yīng),最后別忘了關(guān)閉 socket連接。

僅用幾行代碼,我們就實現(xiàn)了一個極簡的 HTTP 客戶端程序,接下來對其進行測試。

首先在終端中使用 Python 運行服務(wù)器端程序:python3 server.py。然后在另一個終端中使用 Python 運行客戶端程序:python3 client.py。

可以看到客戶端打印結(jié)果如下:b'HTTP/1.1 200 OK\r\nContent-Type: text/html\r\n\r\n

Hello World

'

以上,我們實現(xiàn)了一個極簡的 HTTP 客戶端。

參考 requests 實現(xiàn)客戶端

用 Python 寫過爬蟲的同學(xué),一定聽說或使用過 requests 庫,以下是使用 requests 訪問 Hello World 服務(wù)端程序的示例代碼:# demo_requests.py

import requests

response = requests.request('GET', 'http://127.0.0.1:8000/')

print(response.status_code) # 響應(yīng)狀態(tài)碼

print('--------------------')

print(response.headers) # 響應(yīng)頭

print('--------------------')

print(response.text) # 響應(yīng)體

在終端中使用 python3 demo_requests.py 運行此程序,將打印如下結(jié)果:200

--------------------

{'Content-Type': 'text/html'}

--------------------

Hello World

接下來修改我們上面實現(xiàn)的極簡 HTTP 客戶端程序,使其能夠支持 response.status_code、response.headers 和 response.text功能。# client.py

import socket

from urllib.parse import urlparse

class HTTPClient(object):

"""HTTP 客戶端"""

def __init__(self):

# 創(chuàng)建 socket 對象

self.sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 初始化數(shù)據(jù)

self.status_code = 200

self.headers = {}

self.text = ''

def __del__(self):

# 關(guān)閉連接

self.sock.close()

def connect(self, ip, port):

"""建立連接"""

self.sock.connect((ip, port))

def request(self, method, url):

"""請求"""

# URL 解析

parse_result = urlparse(url)

ip = parse_result.hostname

port = parse_result.port or 80

host = parse_result.netloc

path = parse_result.path

# 建立連接

self.connect(ip, port)

# 構(gòu)造請求數(shù)據(jù)

send_data = f'{method} {path} HTTP/1.1\r\nHost: {host}\r\n\r\n'.encode('utf-8')

# 發(fā)送請求

self.sock.send(send_data)

# 接收服務(wù)端響應(yīng)的數(shù)據(jù)

data = self.recv_data()

# 解析響應(yīng)數(shù)據(jù)

self.parse_data(data)

def recv_data(self):

"""接收數(shù)據(jù)"""

data = b''

while True:

chunk = self.sock.recv(1024)

data += chunk

if len(chunk) < 1024:

break

return data.decode('utf-8')

def parse_data(self, data):

"""解析數(shù)據(jù)"""

header, self.text = data.split('\r\n\r\n', 1)

status_line, header = header.split('\r\n', 1)

for item in header.split('\r\n'):

k, v = item.split(': ')

self.headers[k] = v

self.status_code = status_line.split(' ')[1]

if __name__ == '__main__':

client = HTTPClient()

client.request('GET', 'http://127.0.0.1:8000/')

print(client.status_code)

print('--------------------')

print(client.headers)

print('--------------------')

print(client.text)

代碼實現(xiàn)比較簡單,我寫了較為詳細(xì)的注釋,相信你能夠看懂。其中使用了內(nèi)置函數(shù) urlparse ,此函數(shù)能夠根據(jù) URL 格式規(guī)則將 URL 拆分成多個部分。

在終端中使用 python3 client.py 運行此程序,打印結(jié)果與使用 requests 的結(jié)果完全相同。200

--------------------

{'Content-Type': 'text/html'}

--------------------

Hello World

僅用幾十行代碼,我們就實現(xiàn)了一個簡易版的 HTTP 客戶端程序,并且還實現(xiàn)了類似 requests 庫的功能。

接下來你可以嘗試用它去訪問現(xiàn)實世界中真實的 URL,比如訪問 http://httpbin.org/get,看看打印結(jié)果如何。

P.S.

Web 開發(fā)本質(zhì)是圍繞著 HTTP 協(xié)議進行的,HTTP 協(xié)議是 Web 開發(fā)的基石。所以對于何為 HTTP 服務(wù)端、何為 HTTP 客戶端的概念不夠清晰的話,實際上都是對 HTTP 協(xié)議不夠理解。

最后,給大家留一道作業(yè)題,實現(xiàn) requests 庫的 response.json() 方法。

聯(lián)系我:

總結(jié)

以上是生活随笔為你收集整理的python客户端软件开发_用 Python 实现一个简易版 HTTP 客户端的全部內(nèi)容,希望文章能夠幫你解決所遇到的問題。

如果覺得生活随笔網(wǎng)站內(nèi)容還不錯,歡迎將生活随笔推薦給好友。