??蘇州程式大白用萬字決議Python網路編程??《??記得收藏??》
- 目錄
-
🏳??🌈開講啦!!!!🏳??🌈蘇州程式大白🏳??🌈 - 🌟博主介紹
- 計算機網路基礎
- IP地址的介紹
- 埠和埠號
- 協議
- TCP網路開發流程
- TCP客戶端程式開發流程
- TCP服務端程式開發流程
- TCP網路開發
- socket類
- TCP客戶端程式開發
- TCP服務端程式開發
- 網路開發注意點
- socket中 send 與 recv原理剖析
- HTTP協議
- 什么是URL
- HTTP請求報文
- GET請求報文
- POST請求報文
- POST與GET之間的區別
- HTTP回應報文
- HTTP回應報文
- 常見HTTP狀態碼
- 使用Python自帶的HTTP服務器
- 靜態web服務器是什么
- 如何搭建Python自帶的靜態Web服務器
- 自制靜態Web服務器
- 🌟作者相關的文章、資源分享🌟
目錄
| 🏳??🌈開講啦!!!!🏳??🌈蘇州程式大白🏳??🌈 |

🌟博主介紹
💂 個人主頁:蘇州程式大白
🤟作者介紹:中國DBA聯盟(ACDU)成員,CSDN全國各地程式猿(媛)聚集地管理員,目前從事工業自動化軟體開發作業,擅長C#、Java、機器視覺、底層演算法等語言,2019年成立柒月軟體作業室,
💬如果文章對你有幫助,歡迎關注、點贊、收藏(一鍵三連)和C#、Halcon、python+opencv、VUE、各大公司面試等一些訂閱專欄哦
🎗? 承接各種軟體開發專案
💅 有任何問題歡迎私信,看到會及時回復
👤 微信號:stbsl6,微信公眾號:蘇州程式大白
🎯 想加入技術交流群的可以加我好友,群里會分享學習資料
計算機網路基礎
IP地址的介紹
IP地址的概念: ?
-
IP地址(Internet Protocol Address)是指互聯網協議地址,又譯為網際協議地址,
-
IP地址是IP協議提供的一種統一的地址格式,它為互聯網上的每一個網路和每一臺主機分配一個邏輯地址,以此來屏蔽物理地址的差異,

IP地址的表現形式: ? -
IP 地址分為兩類: IPv4 和 IPv6,
-
IPv4 是普遍正在被廣泛使用的IP協議,
-
IPv6 是現階段為了解決IPv4地址不夠用的情況而正在普及的下一代IP協議,
-
IPv4 是由點分十進制組成,
-
IPv6 是由冒號十六進制組成,
IP地址的作用: ?
-
IP 地址的作用是標識網路中唯一的一臺設備的,也就是說通過IP地址能夠找到網路中某臺設備,

查看IP地址: -
Linux 和 mac OS 使用
ifconfig這個命令,

- Windows 使用 ipconfig 這個命令

埠和埠號
什么是埠、什么是埠號
-
即為資料傳輸的通道,若將IP地址比作一座房子的地址 ,那么埠就是出入房子的門;
-
然而真正的房子只有幾個門,但是一個IP地址的埠可以有65536個;
-
埠是通過埠號來標記的,埠號只有整數,范圍是從0 到65535,
埠號的分類
-
知名埠:0 - 1023,
-
動態埠:1024 - 65535,
協議
TCP協議
-
TCP的概念
-
傳輸控制協議(Transmission Control Protocol)是一種面向連接的、可靠的、基于位元組流的傳輸層通信協議,
TCP通信流程
1、建立連接(三次握手),
2、傳輸資料,
3、關閉連接(四次揮手),
TCP的特點
-
面向連接,
-
可靠傳輸,
UDP協議
- 概念:用戶資料報協議(User Datagram Protocol)是OSI參考模型中一種無連接的傳輸層協議,
UDP的特點
-
面向報文,
-
無連接,
-
吞吐量不受擁擠控制演算法的調節,
socket
-
什么是socket?
網路套接字(英語:Network socket;又譯網路套接字、網路介面、網路插槽)在計算機科學中是電腦網路中行程間資料流的端點,是一種作業系統提供的行程間通信機制, -
socket的作用
行程之間網路資料傳輸,

TCP網路開發流程

TCP客戶端程式開發流程
- 流程梳理:
1、創建服務端套接字物件,
2、系結監聽埠,
3、設定監聽,
4、等待客戶端的連接請求,
5、接受資料,
6、回傳資料,
7、關閉套接字,
TCP服務端程式開發流程
- 流程梳理:
1、創建客戶端套接字物件,
2、和服務端套接字建立連接,
3、發送資料,
4、接受資料,
5、關閉客戶端套接字,
TCP網路開發
socket類
Python 中,我們用 socket()函式來創建套接字,語法格式如下: ?
import socket
socket.socket([family[, type[, proto]]])
- 引數:
| 引數 | 描述 |
|---|---|
| family | 套接字家族可以使AF_UNIX或者AF_INET |
| family | 套接字家族可以使AF_UNIX或者AF_INET |
| type | 套接字型別可以根據是面向連接的還是非連接分為SOCK_STREAM或SOCK_DGRAM |
| protocol | 一般不填默認為0 |
- Socket 型別:
| 型別 | 描述 |
|---|---|
| socket.AF_UNIX | 只能夠用于單一的Unix系統行程間通信 |
| socket.AF_INET | 服務端與客戶端之間通訊協議(IPv4) |
| socket.AF_INET6 | 服務端與客戶端之間通訊協議(IPv6) |
| socket.SOCK_STREAM | 使用TCP傳輸協議進行資料傳輸(流式socket) |
| socket.SOCK_DGRAM | 使用UDP傳輸協議進行資料傳輸(資料報式socket) |
| socket.SOCK_RAW | 原始套接字;可以處理普通套接字無法處理的ICMP,IGMP等特殊的網路報文 |
| socket.SOCK_RDM | 提供可靠的UDP資料報連接,即保證交付資料報但不保證資料 |
| socket.SOCK_SEQPACKET | 提供連續可靠的資料包連接 |
- socket類方法:
| 方法 | 描述 |
|---|---|
| _socket.bind(address) | 將套接字系結到地址;在AF_INET下,以元組(host,port)的形式表示地址, |
| _socket.listen(backlog) | 開始監聽傳入連接,backlog指定在拒絕連接之前,可以掛起的最大連接數量, |
| _socket.setblocking(bool) | 是否阻塞(默認True),如果設定False,那么accept和recv時一旦無資料,則報錯, |
| _socket.accept() | 接受連接并回傳(conn,address),其中conn是新的套接字物件,可以用來接收和發送資料,address是客戶端的地址, |
| _socket.connect(address) | 連接到address處的套接字,一般情況下address的格式為元組(hostname,port),如果連接出錯,回傳socket.error錯誤, |
| _socket.connect_ex(address) | 同上,只不過會有回傳值,連接成功時回傳 0 ,連接失敗時候回傳錯誤代碼 |
| _socket.close() | 關閉套接字連接 |
| _socket.recv(bufsize[,flag]) | 接受套接字的資料,資料以字串形式回傳,bufsize指定最多可以接收的數量,flag提供有關訊息的其他資訊,通常可以忽略, |
| _socket.recvfrom(bufsize[.flag]) | 與recv()類似,但回傳值是(data,address),其中data是包含接收資料的字串,address是發送資料的套接字地址, |
| _socket.send(string[,flag]) | 將string中的資料發送到連接的套接字,回傳值是要發送的位元組數量,該數量可能小于string的位元組大小,即:可能未將指定內容全部發送, |
| _socket.sendall(string[,flag]) | 將string中的資料發送到連接的套接字,但在回傳之前會嘗試發送所有資料,成功回傳None,失敗則拋出例外,內部通過遞回呼叫send,將所有內容發送出去, |
| _socket.sendto(string[,flag],address) | 將資料發送到套接字,address是形式為(ipaddr,port)的元組,指定遠程地址,回傳值是發送的位元組數,該函式主要用于UDP協議, |
| _socket.settimeout(timeout) | 設定套接字操作的超時期,timeout是一個浮點數,單位是秒,值為None表示沒有超時期, |
| _socket.getpeername() | 回傳連接套接字的遠程地址,回傳值通常是元組(ipaddr,port), |
| _socket.getsockname() | 回傳套接字自己的地址,通常是一個元組(ipaddr,port) |
| _socket.fileno() | 套接字的檔案描述符 |
TCP客戶端程式開發
import socket # 匯入socket包
if __name__ == '__main__':
# 創建socket套接字 AF_INET -> 采用IPv4 ;SOCK_STREAM -> 采用TCP傳輸協議
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 與服務端建立連接
client_socket.connect(('127.0.0.1', 9091))
# 準備需要發送的資料,使用UTF-8進行編碼
_data = 'Connect Succces!'.encode('utf-8')
# 發送資料
client_socket.send(_data)
# 獲取服務端回傳資料
_recv = client_socket.recv(1024)
# 列印服務端回傳的原始資料
print('獲得來自服務器的原始資料:', _recv)
# 對資料進行解碼
_decode = _recv.decode('utf-8')
print('獲得來自服務器的資料:', _decode)
# 關閉socket套接字
client_socket.close()
TCP服務端程式開發
單任務版: ?
import socket # 匯入socket包
if __name__ == '__main__':
# 創建socket套接字 AF_INET -> 采用IPv4 ;SOCK_STREAM -> 采用TCP傳輸協議
server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
# 設定啟用埠復用,當程式結束時,立即釋放埠號
server_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
# 系結監聽埠號
server_socket.bind(("0.0.0.0", 9091))
# 配置監聽最大等待連接個數
server_socket.listen(128)
# 等待客戶端建立連接請求,回傳(conn,info),若無連接則會一直保持阻塞狀態
# 其中conn由service_socket接收,是與客戶端建立連接的套接字
# info由client_info接收,是客戶端的地址與埠資訊
service_socket, client_info = server_socket.accept()
print('客戶端的IP地址和埠號:', client_info)
# 獲取客戶端發送的原始資料
_renv = service_socket.recv(1024)
# 獲取原始資料的長度
_length = len(_renv)
print('接收資料的長度為:', _length)
# 對原始資料進行解碼
_decode = _renv.decode('utf-8')
print('接收客戶端的資料為:', _decode)
# 準備需要回傳的資料,使用UTF-8進行編碼
_data = '問題處理中...'.encode('utf-8')
# 發送資料
service_socket.send(_data)
# 關閉服務端與客戶端的套接字
service_socket.close()
# 關閉服務端套接字
server_socket.close()
多任務版: ?
在現實生產環境中,一個服務端不可能只就服務于一個客戶端;通常一個服務端是要能服務多個客戶端,以下是多任務的實作思路:
1、撰寫一個TCP服務端程式,回圈等待接受客戶端的連接請求,
2、當客戶端和服務端建立連接成功,創建子執行緒,使用子執行緒專門處理客戶端的請求,防止主執行緒阻塞,
3、把創建的子執行緒設定成為守護主執行緒,防止主執行緒無法退出,
import socket
import threading
# 客戶端服務處理函式
def handle_client_request(_socket, _info):
while True:
# 獲取客戶端發送的原始資料
_data = _socket.recv(1024)
# 容器型別判斷是否有資料可以直接使用if陳述句進行判斷,如果容器型別里面有資料表示條件成立,否則條件失敗
# 容器型別: 串列、字典、元組、字串、set、range、二進制資料
if _data:
print(_data.decode("utf-8"), _info)
# 回復
_socket.send("資料接收正常...".encode("utf-8"))
else:
print("客戶端下線了:", _info)
break
# 關閉服務端與客戶端的套接字
_socket.close()
if __name__ == '__main__':
# 創建socket套接字 AF_INET -> 采用IPv4 ;SOCK_STREAM -> 采用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(("", 9090))
# 配置監聽最大等待連接個數
tcp_server_socket.listen(128)
# 回圈等待接收客戶端的連接請求
while True:
# 等待客戶端建立連接請求,回傳(conn,info),若無連接則會一直保持阻塞狀態
# 其中conn由service_socket接收,是與客戶端建立連接的套接字
# info由client_info接收,是客戶端的地址與埠資訊
service_socket, client_info = tcp_server_socket.accept()
print("客戶端連接成功:", client_info)
# 當客戶端和服務端建立連接成功以后,創建一個子執行緒處理接下來的客戶端訊息
client_thread = threading.Thread(target=handle_client_request, args=(service_socket, client_info))
# 設定守護主執行緒,當主執行緒退出時自動終止子執行緒
client_thread.setDaemon(True)
# 啟動子執行緒
client_thread.start()
網路開發注意點
1、當 TCP 客戶端程式想要和 TCP 服務端程式進行通信的時候必須要先建立連接,
2、TCP 客戶端程式一般不需要系結埠號,因為客戶端是主動發起建立連接的,
3、TCP 服務端程式必須系結埠號,否則客戶端找不到這個 TCP 服務端程式,
4、listen 后的套接字是被動套接字,只負責接收新的客戶端的連接請求,不能收發訊息,
5、當 TCP 客戶端程式和 TCP 服務端程式連接成功后, TCP 服務器端程式會產生一個新的套接字,收發客戶端訊息使用該套接字,
6、關閉 accept 回傳的套接字意味著和這個客戶端已經通信完畢,
7、關閉 listen 后的套接字意味著服務端的套接字關閉了,會導致新的客戶端不能連接服務端,但是之前已經接成功的客戶端還能正常通信,
8、當客戶端的套接字呼叫 close 后,服務器端的 recv 會解阻塞,回傳的資料長度為0,服務端可以通過回傳資料的長度來判斷客戶端是否已經下線,反之服務端關閉套接字,客戶端的 recv 也會解阻塞,回傳的資料長度也為0,
socket中 send 與 recv原理剖析

send原理 ?
Q:send是不是直接把資料發給服務端?
A:不是,要想發資料,必須得通過網卡發送資料,應用程式是無法直接通過網卡發送資料的,它需要呼叫作業系統介面,也就是說,應用程式把發送的資料先寫入到發送緩沖區(記憶體中的一片空間),再由作業系統控制網卡把發送緩沖區的資料發送給服務端網卡 ,
recv原理 ?
Q:renv是不是直接從客戶端接收資料?
A:不是,應用軟體是無法直接通過網卡接收資料的,它需要呼叫作業系統介面,由作業系統通過網卡接收資料,把接收的資料寫入到接識訓沖區(記憶體中的一片空間),應用程式再從接收快取區獲取客戶端發送的資料,
HTTP協議
什么是HTTP協議 ?
- HTTP協議介紹:
1、HTTP 協議的全稱是(HyperText Transfer Protocol),翻譯過來就是超文本傳輸協議,
2、超文本是超級文本的縮寫,是指超越文本限制或者超鏈接,比如:圖片、音樂、視頻、超鏈接等等都屬于超文本,
3、HTTP 協議的制作者是蒂姆·伯納斯-李,1991年設計出來的,HTTP 協議設計之前目的是傳輸網頁資料的,現在允許傳輸任意型別的資料,
4、傳輸 HTTP 協議格式的資料是基于 TCP 傳輸協議的,發送資料之前需要先建立連接,
- HTTP協議的作用:
1、規定瀏覽器和web服務器通信的資料格式,
- 瀏覽器訪問Web服務器的通訊程序

什么是URL
什么是URL: ?
1、URL的英文全拼是(Uniform Resoure Locator),表達的意思是統一資源定位符,通俗理解就是網路資源地址,也就是我們常說的網址,
- URL的組成
URL的樣子:

URL的組成部分:
1、協議部分: https://、http://、ftp://,
2、域名部分: news.163.com,
3、資源路徑部分: /18/1122/10/E178J2O4000189FH.html,
域名:
- 域名就是IP地址的別名,它是用點進行分割使用英文字母和數字組成的名字,使用域名目的就是方便的記住某臺主機IP地址,
URL的擴展:
-
model遵守Codable協議,
-
用JSONEncoder進行決議,
定義ConvertToStringable協議
protocol ConvertToStringable {
associatedtype Result: Codable
var valueString: String { get }
}
extension ConvertToStringable {
func toString(result: Result) -> String {
let data = try? JSONEncoder().encode(result)
guard let da = data else { return "" }
guard let st = String.init(data: da, encoding: .utf8) else { return "" }
return st
}
}
我們使用關聯型別來匹配不同的模型實體,然后我們在每個需要model轉為JSON格式字串的model里擴展一下model: ?
struct UserInfo: Codable {
var name: String
var age: Int
var avator: String
}
extension UserInfo: ConvertToStringable {
typealias Result = UserInfo
var valueString: String { return toString(result: self) }
}
查詢引數部分: ?page=1&count=10 ?
- 引數說明:
? 后面的 page 表示第一個引數,后面的引數都使用 & 進行連接,
HTTP請求報文
GET請求報文
---- 請求行 ----
GET / HTTP/1.1 # GET請求方式 請求資源路徑 HTTP協議版本
---- 請求頭 -----
Host: www.smartfox.cc # 服務器的主機地址和埠號,默認是80
Connection: keep-alive # 和服務端保持長連接
Upgrade-Insecure-Requests: 1 # 讓瀏覽器升級不安全請求,使用https請求
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36 # 用戶代理,也就是客戶端的名稱
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8 # 可接受的資料型別
Accept-Encoding: gzip, deflate # 可接受的壓縮格式
Accept-Language: zh-CN,zh;q=0.9 #可接受的語言
Cookie: csrftoken=ZIVKMSEdmdJbowTnXtRPXByIqxK1WF1ronGQXKWdp51WnSvmlRyqsKzZFPAojcLF; sessionid=as3sop6t2igilg76zll45m045udfsoa7; # 登錄用戶的身份標識
---- 空行 ----
也就是說GET請求報文是由以下部分組成的: ?
-
請求行,
-
請求頭,
-
空行,
POST請求報文
---- 請求行 ----
POST /admin.php?next=index.php HTTP/1.1 # POST請求方式 請求資源路徑 HTTP協議版本
---- 請求頭 ----
Host: www.smartfox.cc # 服務器的主機地址和埠號,默認是80
Connection: keep-alive # 和服務端保持長連接
Content-Type: application/x-www-form-urlencoded # 告訴服務端請求的資料型別
User-Agent: Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/84.0.4147.135 Safari/537.36 # 客戶端的名稱
---- 空行 ----
---- 請求體 ----
username=admin&pass=admin # 請求引數
也就是說POST報文是由以下部分組成: ?
-
請求行
-
請求頭
-
空行
-
請求體
POST與GET之間的區別

-
一個HTTP請求報文可以由請求行、請求頭、空行和請求體4個部分組成,
-
GET方式的請求報文沒有請求體,只有請求行、請求頭、空行組成,
-
POST方式的請求報文可以有請求行、請求頭、空行、請求體四部分組成,
注意:POST方式可以允許沒有請求體,但是這種格式很少見, ?
HTTP回應報文
HTTP回應報文
--- 回應行/狀態行 ---
HTTP/1.1 200 OK # HTTP協議版本 狀態碼 狀態描述
--- 回應頭 ---
Server: Tengine # 服務器名稱
Content-Type: text/html; charset=UTF-8 # 內容型別
Transfer-Encoding: chunked # 發送給客戶端內容不確定內容長度,發送結束的標記是0\r\n, Content-Length表示服務端確定發送給客戶端的內容大小,但是二者只能用其一,
Connection: keep-alive # 和客戶端保持長連接
Date: Fri, 23 Nov 2018 02:01:05 GMT # 服務端的回應時間
--- 空行 ---
--- 回應體 ---
<!DOCTYPE html><html lang=“en”>…</html> # 回應給客戶端的資料
所以一個成熟的HTTP回應報文是由以下部分組成的: ?

常見HTTP狀態碼
| 狀態碼 | 狀態 | 說明 |
|---|---|---|
| 200 | OK | 請求成功 |
| 201 | Created | 請求已經被實作,而且所需資源已建立,且其URI已經隨頭部資訊回傳, |
| 202 | Accepted | 服務器已接受請求,但尚未處理, |
| 307 | Temporary Redirect | 重定向 |
| 400 | Bad Request | 錯誤的請求,請求地址或者引數有誤 |
| 403 | Forbidden | 服務器已經理解請求,但是拒絕執行它, |
| 404 | Not Found | 請求資源在服務器不存在 |
| 500 | Internal Server Error | 服務器內部源代碼出現錯誤 |
| 502 | Bad Gateway | 作為網關或代理的服務器嘗試執行請求時,從上游服務接到無效的回應, |
使用Python自帶的HTTP服務器
靜態web服務器是什么
-
可以為發出請求的瀏覽器提供靜態檔案的程式,
-
平時我們瀏覽百度新聞資料的時候,每天的新聞資料都會發生變化,那訪問的這個頁面就是動態的,而我們開發的是靜態的,頁面的資料不會發生變化,
如何搭建Python自帶的靜態Web服務器
在Python3的模塊中,官方加入了http模塊,我們可以直接呼叫運行它,讓他作為提供靜態Web的服務,
-
語法格式:
python3 -m http.server [PORT], -
-m表示運行包里面的模塊, -
執行這個命令的時候,需要進入你自己指定靜態檔案的目錄,然后通過瀏覽器就能訪問對應的靜態檔案了,
python3 -m http.server 8080

自制靜態Web服務器
回傳固定頁面資料 ?
import socket
if __name__ == '__main__':
_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
_server.bind(("", 9091))
_server.listen(10)
while True:
_client, _client_info = _server.accept()
_request_data = _client.recv(4096)
print(_request_data)
with open("static/index.html", 'rb') as _file:
file_data = _file.read()
print(file_data)
response_line = "HTTP/1.1 200 OK\r\n"
response_head = "Server: NGINX/14.8\r\n"
response_body = file_data
response_data = (response_line + response_head + "\r\n").encode('utf-8') + response_body
print(response_data)
_client.send(response_data)
_client.close()
回傳指定頁面資料 ?
import socket
def init_server():
_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
_server.bind(("", 9091))
print("Server Listen : 0.0.0.0:9091")
_server.listen(128)
return _server
def service_logic(_server):
_service, _info = _server.accept()
renv_data = _service.recv(4096)
if len(renv_data) == 0:
print('客戶端', _info, '離線')
_service.close()
return
_data = renv_data.decode('utf-8')
url = _data.split(" ", maxsplit=2)
uri = url[1]
print(uri)
if uri == "/":
uri = '/index.html'
try:
with open("static" + uri, "rb") as _file:
response_body = _file.read()
except Exception as e:
response_line = "HTTP/1.1 404 Not Found\r\n"
response_header = "Server: PythonWeb1.0\r\n"
with open("static/error.html", "rb") as _file:
response_body = _file.read()
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
_service.send(response_data)
else:
response_line = "HTTP1.1 200 OK\r\n"
response_header = "Server: PythonWeb1.0\r\n"
response_data = (response_line + response_header + "\r\n").encode('utf-8') + response_body
_service.send(response_data)
finally:
_service.close()
if __name__ == '__main__':
server = init_server()
while True:
service_logic(server)
多任務版 ?
import socket
import threading
def init_server():
_server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
_server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
_server.bind(("", 9091))
print("Server Listen : 0.0.0.0:9091")
_server.listen(128)
return _server
def handle_client(_service, _info):
renv_data = _service.recv(4096)
if len(renv_data) == 0:
print('客戶端', _info, '離線')
_service.close()
return
_data = renv_data.decode('utf-8')
url = _data.split(" ", maxsplit=2)
uri = url[1]
print(uri)
if uri == "/":
uri = '/index.html'
try:
with open("static" + uri, "rb") as _file:
response_body = _file.read()
except Exception as e:
response_line = "HTTP/1.1 404 Not Found\r\n"
response_header = "Server: PythonWeb1.0\r\n"
with open("static/error.html", "rb") as _file:
response_body = _file.read()
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
_service.send(response_data)
else:
response_line = "HTTP1.1 200 OK\r\n"
response_header = "Server: PythonWeb1.0\r\n"
response_data = (response_line + response_header + "\r\n").encode('utf-8') + response_body
_service.send(response_data)
finally:
_service.close()
def service_logic(_server):
_services, _info = _server.accept()
handle_service = threading.Thread(target=handle_client, args=(_services, _info))
handle_service.daemon = True
handle_service.start()
if __name__ == '__main__':
server = init_server()
while True:
service_logic(server)
面向物件版 ?
import socket
import threading
class WebServer(object):
def __init__(self, addr: str = '0.0.0.0', port: int = 9091) -> None:
self._server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
self._server.bind((addr, port))
print(f"Server Listen!{addr}:{port}")
self._server.listen(128)
def service_logic(self) -> None:
while True:
_services, _info = self._server.accept()
handle_service = threading.Thread(target=self.handle_client, args=(_services, _info))
handle_service.daemon = True
handle_service.start()
@staticmethod
def handle_client(_service: socket.socket, _info: tuple) -> None:
renv_data = _service.recv(4096)
if len(renv_data) == 0:
print('客戶端', _info, '離線')
_service.close()
return
_data = renv_data.decode('utf-8')
url = _data.split(" ", maxsplit=2)
uri = url[1]
print(uri)
if uri == "/":
uri = '/index.html'
try:
with open("static" + uri, "rb") as _file:
response_body = _file.read()
except Exception as e:
response_line = "HTTP/1.1 404 Not Found\r\n"
response_header = "Server: PythonWeb1.0\r\n"
with open("static/error.html", "rb") as _file:
response_body = _file.read()
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
_service.send(response_data)
else:
response_line = "HTTP1.1 200 OK\r\n"
response_header = "Server: PythonWeb1.0\r\n"
response_data = (response_line + response_header + "\r\n").encode('utf-8') + response_body
_service.send(response_data)
finally:
_service.close()
if __name__ == '__main__':
server = WebServer()
server.service_logic()
命令列啟動動態系結埠號 ?
import socket
import threading
import sys
class WebServer(object):
def __init__(self, addr: str = '0.0.0.0', port: int = 9091) -> None:
self._server = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self._server.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, True)
self._server.bind((addr, port))
print(f"Server Listen!{addr}:{port}")
self._server.listen(128)
def service_logic(self) -> None:
while True:
_services, _info = self._server.accept()
handle_service = threading.Thread(target=self.handle_client, args=(_services, _info))
handle_service.daemon = True
handle_service.start()
@staticmethod
def handle_client(_service: socket.socket, _info: tuple) -> None:
renv_data = _service.recv(4096)
if len(renv_data) == 0:
print('客戶端', _info, '離線')
_service.close()
return
_data = renv_data.decode('utf-8')
url = _data.split(" ", maxsplit=2)
uri = url[1]
print(uri)
if uri == "/":
uri = '/index.html'
try:
with open("static" + uri, "rb") as _file:
response_body = _file.read()
except Exception as e:
response_line = "HTTP/1.1 404 Not Found\r\n"
response_header = "Server: PythonWeb1.0\r\n"
with open("static/error.html", "rb") as _file:
response_body = _file.read()
response_data = (response_line + response_header + "\r\n").encode("utf-8") + response_body
_service.send(response_data)
else:
response_line = "HTTP1.1 200 OK\r\n"
response_header = "Server: PythonWeb1.0\r\n"
response_data = (response_line + response_header + "\r\n").encode('utf-8') + response_body
_service.send(response_data)
finally:
_service.close()
if __name__ == '__main__':
args = sys.argv
if len(sys.argv) != 2:
print("執行命令如下: python3 xxx.py 8000")
exit(0)
# 判斷字串是否都是數字組成
if not sys.argv[1].isdigit():
print("執行命令如下: python3 xxx.py 8000")
exit(0)
port = int(sys.argv[1])
server = WebServer(port=port)
server.service_logic()
🌟作者相關的文章、資源分享🌟
🌟讓天下沒有學不會的技術🌟
學習C#不再是難問題
🌳《C#入門到高級教程》🌳
有關C#實戰專案
👉C#RS232C通訊原始碼👈
👉C#委托資料傳輸👈
👉C# Modbus TCP 源代碼👈
👉C# 倉庫管理系統原始碼👈
👉C# 歐姆龍通訊Demo👈
👉C#+WPF+SQL目前在某市上線的車管所攝像系統👈
👉2021C#與Halcon視覺通用的框架👈
👉2021年視覺專案中利用C#完成三菱PLC與上位機的通訊👈
👉VP聯合開源深度學習編程(WPF)👈
?有關C#專案歡迎各位查看個人主頁?
🌟機器視覺、深度學習🌟
學習機器視覺、深度學習不再是難問題
🌌《Halcon入門到精通》🌌
🌌《深度學習資料與教程》🌌
有關機器視覺、深度學習實戰
👉2021年C#+HALCON視覺軟體👈
👉2021年C#+HALCON實作模板匹配👈
👉C#集成Halcon的深度學習軟體👈
👉C#集成Halcon的深度學習軟體,帶[MNIST例子]資料集👈
👉C#支持等比例縮放拖動的halcon WPF開源表單控制元件👈
👉2021年Labview聯合HALCON👈
👉2021年Labview聯合Visionpro👈
👉基于Halcon及VS的動車組制動閘片厚度自動識別模塊👈
?有關機器視覺、深度學習實戰歡迎各位查看個人主頁?
🌟Java、資料庫教程與專案🌟
學習Java、資料庫教程不再是難問題
🍏《JAVA入門到高級教程》🍏
🍏《資料庫入門到高級教程》🍏
有關Java、資料庫專案實戰
👉Java經典懷舊小霸王網頁游戲機原始碼增強版👈
👉js+css類似網頁版網易音樂原始碼👈
👉Java物業管理系統+小程式原始碼👈
👉JavaWeb家居電子商城👈
👉JAVA酒店客房預定管理系統的設計與實作SQLserver👈
👉JAVA圖書管理系統的研究與開發MYSQL👈
?有關Java、資料庫教程與專案實戰歡迎各位查看個人主頁?
🌟分享Python知識講解、分享🌟
學習Python不再是難問題
🥝《Python知識、專案專欄》🥝
🥝《Python 檢測抖音關注賬號是否封號程》🥝
🥝《手把手教你Python+Qt5安裝與使用》🥝
🥝《用一萬字給小白全面講解python編程基礎問答》🥝
🥝《Python 繪制Android CPU和記憶體增長曲線》🥝
有關Python專案實戰
👉Python基于Django圖書管理系統👈
👉Python管理系統👈
👉2021年9個常用的python爬蟲原始碼👈
👉python二維碼生成器👈
?有關Python教程與專案實戰歡迎各位查看個人主頁?
🌟分享各大公司面試題、面試流程🌟
面試成功不是難事
🍏《2021年金九銀十最新的VUE面試題??《??記得收藏??》》🍏
🍏《只要你認真看完一萬字??Linux作業系統基礎知識??分分鐘鐘都吊打面試官《??記得收藏??》》🍏
🍏《??用一萬字給小白全面講解python編程基礎問答??《😀記得收藏不然看著看著就不見了😀》》🍏
?有關各大公司面試題、面試流程歡迎各位查看個人主頁?

轉載請註明出處,本文鏈接:https://www.uj5u.com/qita/327865.html
標籤:AI
