如何用Python實現http客戶端和伺服器

来源:https://www.cnblogs.com/subodong/archive/2022/10/09/16773902.html
-Advertisement-
Play Games

python 有許多可視化工具,但本書只介紹Matplotlib。Matplotlib是一種2D的繪圖庫,它可以支持硬拷貝和跨系統的交互,它可以在python腳本,IPython的交互環境下、Web應用程式中使用。該項目是由John Hunter 於2002年啟動,其目的是為python構建MATL ...


功能:客戶端可以向伺服器發送get,post等請求,而伺服器端可以接收這些請求,並返回給客戶端消息。

 

客戶端:

#coding=utf-8
import http.client
from urllib import request, parse


def send_get(url,path,data):#get請求函數
conn = http.client.HTTPConnection(url)
conn.request("GET", path)
r1 = conn.getresponse()
print(r1.status, r1.reason)

data1 = r1.read()
print(data1) #
conn.close()

def send_post(url,path,data,header):#post請求函數
conn = http.client.HTTPConnection(url)#建立連接
conn.request("POST", path,data,header)#用request請求,將信息封裝成幀
r1 = conn.getresponse()
print(r1.status, r1.reason)

data1 = r1.read()
print(data1) #
conn.close()
def send_head(url,path,data,header):
conn = http.client.HTTPConnection(url)
conn.request("HEAD", path,data,header)
r1 = conn.getresponse()
print(r1.status, r1.reason)
data1 = r1.headers #
print(data1) #
conn.close()
def send_put(url,path,filedata,header):
conn = http.client.HTTPConnection(url)
conn.request("PUT", path,filedata,header)
r1 = conn.getresponse()
print(r1.status, r1.reason)

data1 = r1.read() #
print(data1)
conn.close()
def send_option(url,path,data,header):
conn = http.client.HTTPConnection(url)
conn.request("OPTION", path,data,header)
r1 = conn.getresponse()
print(r1.status, r1.reason)
data1 = r1.headers #
print(data1) #
conn.close()
def delete_option(url,path,filename,header):
conn = http.client.HTTPConnection(url)
conn.request("DELETE", path, filename, header)
r1 = conn.getresponse()
print(r1.status, r1.reason)

data1 = r1.read() #
print(data1)
conn.close()
if __name__ == '__main__':

url="localhost:8100"
data = {
'my post data': 'I am client , hello world',
}
datas = parse.urlencode(data).encode('utf-8')

headers = {"Content-type": "application/x-www-form-urlencoded","Accept": "text/plain"}
while True:
command = input("輸入請求的命令:")
if command =='get':
print("----------發送get請求:-----------")
send_get(url,path="",data="None")
elif command=='post':
print("----------發送post請求-----------")
send_post(url, path="",data=datas,header=headers)

elif command =='put':
print("----------發送put請求-----------")
file = input("輸入要發送的文件名:")
tfile=open(file,encoding="UTF-8",mode='r')
filedatas=tfile.read()
fileheaders = {"Content-type": "text/plain", "Accept": "text/plain",\
"content-length":str(len(filedatas))}
send_put(url, path="E:/pythonProject2/httpweb/", filedata=filedatas, header=fileheaders)
elif command=='head':
print("----------發送head請求:-----------")
send_head(url, path="", data=datas, header=headers)
elif command=='option':
print("----------發送option請求:-----------")
send_option(url,path="",data=datas,header=headers)
elif command=='delete':
print("----------發送delete請求-----------")
file = input("輸入要刪除的文件名:")
fileheaders = {"Content-type": "text/plain", "Accept": "text/plain"}
delete_option(url, path="E:/pythonProject2/httpweb/", filename = file, header=fileheaders)
elif command == 'exit':
break
伺服器:
# -*- coding: utf-8 -*-

import socket
import re
import os
import threading
import urllib.parse


def service_client(new_socket):
# 為這個客戶端返回數據
# 1.接收瀏覽器發過來的請求,即http請求
# GET / HTTP/1.1
request = new_socket.recv(1024).decode('utf-8')
request_header_lines = request.splitlines()
print(request_header_lines)
data = request_header_lines[-1]
# ret = re.match(r'[^/]+(/[^ ]*)', request_header_lines[0])
ret = list(request_header_lines[0].split(' '))[1]
method = list(request_header_lines[0].split(' '))[0]
path_name = "/"

if method == 'GET':
if ret:
path = ret
path_name = urllib.parse.unquote(path) # 瀏覽器請求的路徑中帶有中文,會被自動編碼,需要先解碼成中文,才能找到後臺中對應的html文件
print("請求路徑:{}".format(path_name))

if path_name == "/": # 用戶請求/時,返回咖啡.html頁面
path_name = "/咖啡.html"

# 2.返回http格式的數據給瀏覽器
file_name = 'E:/pythonProject2/httpweb/HTML/' + path_name
try:
f = open(file_name, 'rb')
except:
response = "HTTP/1.1 404 NOT FOUND\r\n"
response += "\r\n"
response += "------file not found------"
new_socket.send(response.encode("utf-8"))
else:
html_content = f.read()
f.close()
# 準備發給瀏覽器的數據 -- header
response = "HTTP/1.1 200 OK\r\n"
response += "\r\n"
new_socket.send(response.encode("utf-8"))
new_socket.send(html_content)
# 關閉套接字
if method == 'POST':
if ret:
path = ret
path_name = urllib.parse.unquote(path) # 瀏覽器請求的路徑中帶有中文,會被自動編碼,需要先解碼成中文,才能找到後臺中對應的html文件
print("請求路徑:{}".format(path_name))
if path_name == "/": # 用戶請求/時,返回咖啡.html頁面
path_name = "/咖啡.html"

# 2.返回http格式的數據給瀏覽器
file_name = 'E:/pythonProject2/httpweb/HTML/' + path_name
response = "HTTP/1.1 200 OK\r\n"
response += "\r\n"
new_socket.send(response.encode("utf-8"))
new_socket.send(file_name.encode("utf-8")+' data:'.encode("utf-8")+data.encode("utf-8"))
if method == 'PUT':
if ret:
path = ret
path_name = urllib.parse.unquote(path) # 瀏覽器請求的路徑中帶有中文,會被自動編碼,需要先解碼成中文,才能找到後臺中對應的html文件
print("請求路徑:{}".format(path_name))
if path_name == "/": # 用戶請求/時,返回咖啡.html頁面
path_name = "/咖啡.html"

# 2.返回http格式的數據給瀏覽器
file_name = list(request_header_lines[0].split(' '))[1] +'test.txt'
content = data.encode('utf-8')
response = "HTTP/1.1 200 OK\r\n"
response += "\r\n"
with open(file_name, 'ab') as f:
f.write(content)
new_socket.send(response.encode("utf-8"))
new_socket.send("finish".encode("utf-8"))
if method=='HEAD':
if ret:
path =ret
path_name = urllib.parse.unquote(path)
print("請求路徑:{}".format(path_name))
if path_name =="/":
path_name = "/咖啡.html"
response = "HTTP/1.1 200 ok\r\n"
new_socket.send(response.encode("utf-8"))
new_socket.send(str(request_header_lines[1:]).encode("utf-8"))
if method=='OPTION':
if ret:
path = ret
path_name = urllib.parse.unquote(path)
print("請求路徑:{}".format(path_name))
if path_name == "/":
path_name = "/咖啡.html"
response = "HTTP/1.1 200 ok\r\n"
new_socket.send(response.encode("utf-8"))
new_socket.send("OPTIONS GET,HEAD,POST,PUT,DELETE".encode("utf-8"))
if method =='DELETE':
if ret:
path = ret
path_name = urllib.parse.unquote(path) # 瀏覽器請求的路徑中帶有中文,會被自動編碼,需要先解碼成中文,才能找到後臺中對應的html文件
print("請求路徑:{}".format(path_name))
if path_name == "/": # 用戶請求/時,返回咖啡.html頁面
path_name = "/咖啡.html"

deletename = request_header_lines[-1]
# print(path_name+deletename)
os.remove(path_name+deletename)
# 2.返回http格式的數據給瀏覽器
content = data.encode('utf-8')
response = "HTTP/1.1 200 OK\r\n"
response += "\r\n"
# with open(file_name, 'ab') as f:
# f.write(content)
new_socket.send(response.encode("utf-8"))
new_socket.send("finish".encode("utf-8"))
# 關閉套接字
new_socket.close()


def main():
# 用來完成整體的控制
# 1.創建套接字
tcp_server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

# 2.綁定
tcp_server_socket.bind(("0.0.0.0", 8100))
# 3.變為監聽套接字
tcp_server_socket.listen(128)
while True:
# 4.等待新客戶端的鏈接
new_socket, client_addr = tcp_server_socket.accept()
# 5.為這個客戶端服務
print("為",client_addr,"服務")
t = threading.Thread(target=service_client, args=(new_socket,))
t.start()

# 關閉監聽套接字
tcp_server_socket.close()


if __name__ == '__main__':
main()

您的分享是我們最大的動力!

-Advertisement-
Play Games
更多相關文章
  • 本文詳細介紹了我國銀行核心系統的定義、位置與邊界,發展歷程、更換核心系統的原因,以及新核心建設的五大模式與其特點對比。希望內容能夠幫助銀行科技從業者建立起對銀行核心系統的整體認知,提供一定積極的指導作用與借鑒意義,從而引發思考並促進行業交流與探討,共同為我國的銀行科技蓬勃發展貢獻自己的智慧與經驗。 ... ...
  • 外觀模式是最常用的結構型設計模式,也是一種非常容易理解的設計模式,其核心就是為多個子系統提供一個統一的介面,將這個介面看作是這些子系統的門面。 ...
  • 上次說了一下Go語言佈道師 Dave Cheney對Go併發的建議,個人覺得最重要的一條,這次主要想說一下這個。 8.3. Never start a goroutine without knowning when it will stop(永遠不要在不知道何時停止的情況下啟動 goroutine) ...
  • Future模式 【1】Future模式是多線程開發中常見的設計模式,它的核心思想是非同步調用。對於Future模式來說,它無法立即返回你需要的數據,但是它會返回一個契約,將來你可以憑藉這個契約去獲取你需要的信息。 【2】通俗一點就是生產者-消費者模型的擴展。經典“生產者-消費者”模型中消息的生產者不 ...
  • stream是java8新出的抽象概念,他可以讓你根據你期望的方式來處理集合數據,能夠輕鬆的執行複雜的查找、過濾和映射數據等操作。Stream 使用一種類似用 SQL 語句從資料庫查詢數據的直觀方式來提供一種對 Java 集合運算和表達的高階抽象。 ...
  • 數據結構基礎—棧和隊列 一、棧和隊列的基本概念和性質 棧和隊列都是特殊的線性表 對他們的操作有著規定和限制:在插入和刪除時只能對某一端操作 棧:只能在一端進行(先進後出) 隊列:只能在表尾插入,在表頭刪除(先進先出) 二、棧 表頭為棧底,表尾為棧頂 1.棧的基本操作和規則 a.進棧和出棧 進棧:棧頂 ...
  • 垃圾回收器 垃圾回收是釋放掉那些不再被使用的記憶體空間的過程。 換句話說,垃圾回收器會去檢查哪些對象超出範圍並且不會再被引用到,然後它回去釋放掉那些對象占用的記憶體空間。這個過程實在 go 程式運行中以併發的方式去進行的,不是 go 程式執行之前,也不是 go 程式執行之後。go 垃圾回收器實現的說明文 ...
  • 前幾天看報道說: 一位小哥用AI繪畫工具Midjourney生成的作品,在美國科羅拉多州博覽會的藝術比賽中獲得了第一名。 作者表示,他多次調整了輸入的提示詞,生成了100多幅畫作,經過數周的修改和挑選,才選出了三幅最滿意的作品。 下圖就是獲獎作品 之前我玩過DF,還寫過一篇文章➡️AI繪畫 Disc ...
一周排行
    -Advertisement-
    Play Games
  • 移動開發(一):使用.NET MAUI開發第一個安卓APP 對於工作多年的C#程式員來說,近來想嘗試開發一款安卓APP,考慮了很久最終選擇使用.NET MAUI這個微軟官方的框架來嘗試體驗開發安卓APP,畢竟是使用Visual Studio開發工具,使用起來也比較的順手,結合微軟官方的教程進行了安卓 ...
  • 前言 QuestPDF 是一個開源 .NET 庫,用於生成 PDF 文檔。使用了C# Fluent API方式可簡化開發、減少錯誤並提高工作效率。利用它可以輕鬆生成 PDF 報告、發票、導出文件等。 項目介紹 QuestPDF 是一個革命性的開源 .NET 庫,它徹底改變了我們生成 PDF 文檔的方 ...
  • 項目地址 項目後端地址: https://github.com/ZyPLJ/ZYTteeHole 項目前端頁面地址: ZyPLJ/TreeHoleVue (github.com) https://github.com/ZyPLJ/TreeHoleVue 目前項目測試訪問地址: http://tree ...
  • 話不多說,直接開乾 一.下載 1.官方鏈接下載: https://www.microsoft.com/zh-cn/sql-server/sql-server-downloads 2.在下載目錄中找到下麵這個小的安裝包 SQL2022-SSEI-Dev.exe,運行開始下載SQL server; 二. ...
  • 前言 隨著物聯網(IoT)技術的迅猛發展,MQTT(消息隊列遙測傳輸)協議憑藉其輕量級和高效性,已成為眾多物聯網應用的首選通信標準。 MQTTnet 作為一個高性能的 .NET 開源庫,為 .NET 平臺上的 MQTT 客戶端與伺服器開發提供了強大的支持。 本文將全面介紹 MQTTnet 的核心功能 ...
  • Serilog支持多種接收器用於日誌存儲,增強器用於添加屬性,LogContext管理動態屬性,支持多種輸出格式包括純文本、JSON及ExpressionTemplate。還提供了自定義格式化選項,適用於不同需求。 ...
  • 目錄簡介獲取 HTML 文檔解析 HTML 文檔測試參考文章 簡介 動態內容網站使用 JavaScript 腳本動態檢索和渲染數據,爬取信息時需要模擬瀏覽器行為,否則獲取到的源碼基本是空的。 本文使用的爬取步驟如下: 使用 Selenium 獲取渲染後的 HTML 文檔 使用 HtmlAgility ...
  • 1.前言 什麼是熱更新 游戲或者軟體更新時,無需重新下載客戶端進行安裝,而是在應用程式啟動的情況下,在內部進行資源或者代碼更新 Unity目前常用熱更新解決方案 HybridCLR,Xlua,ILRuntime等 Unity目前常用資源管理解決方案 AssetBundles,Addressable, ...
  • 本文章主要是在C# ASP.NET Core Web API框架實現向手機發送驗證碼簡訊功能。這裡我選擇是一個互億無線簡訊驗證碼平臺,其實像阿裡雲,騰訊雲上面也可以。 首先我們先去 互億無線 https://www.ihuyi.com/api/sms.html 去註冊一個賬號 註冊完成賬號後,它會送 ...
  • 通過以下方式可以高效,並保證數據同步的可靠性 1.API設計 使用RESTful設計,確保API端點明確,並使用適當的HTTP方法(如POST用於創建,PUT用於更新)。 設計清晰的請求和響應模型,以確保客戶端能夠理解預期格式。 2.數據驗證 在伺服器端進行嚴格的數據驗證,確保接收到的數據符合預期格 ...