Threading 的多執行緒併發
-
threading 的多執行緒併發
threading 的多執行緒併發 對 比多程序併發: *消耗資源較少 *執行緒應該更注意共享資源的操作 *在Pythonh中應該注意GIT問題,網路延遲較高,執行緒併發也是一種可行的操作
實現步驟: 1.建立套接字 2.接受客戶端請求,建立新的執行緒 3.主程式繼續接受其他客戶端連線 4.分支執行緒啟動對應的函式處理客戶端請求 5.當客戶端斷開,則分支執行緒結束
# socket_server.py from socketserver import * # 建立伺服器類 class Server(ForkingMixIn,TCPServer): pass class Handler(StreamRequestHandler): def handle(self): # self.request ==> accept 返回的套接字 print('Connect from', self.request.getpeername()) while True: data = self.request.recv(1024) if not data: break print(data.decode()) self.request.send(b'Recive') if __name__=="__main__": server_addr = ('0.0.0.0', 9999) # 建立伺服器物件 server = Server(server_addr, Handler) # 啟動伺服器 server.serve_forever()
cookie
import traceback 功能:更詳細的列印異常資訊
traceback.print_exc() 功能:更詳細的列印異常資訊
整合模組的使用
python2 SocketServer
python3 socketserver
功能:通過模組的不同 類的組合完成多程序,多執行緒的tcp/udp的併發 StreamRequestHandler 處理tcp套接字請求 DatagramRequestHandler 處理udp套接字請求
TCPServer 建立tcp server UDPServer 建立ucp server
ForkingMixIn 建立多程序 ForkingTCPServer -->ForkingMixIn + TCPServer ForkingUDPServer -->ForkingMixIn + UDPServer
ThreadingMixIn 建立多執行緒 ThreadingTCPServer -->ThreadingMixIn + TCPServer ThreadingUDPServer -->ThreadingMixIn + UDPServer
HTTPServer v2.0
1.接收客戶端請求 2.解析客戶端請求 3.組織資料形成HTTP reponse 4.將資料發給客戶端
升級 1.採用多執行緒併發接收多個客戶端請求 2.基本的請求解析,根據請求返回相應的內容 3.除了可以請求靜態網頁,也可以請求簡單的資料 4.將功能封裝在一個類中
技術點: 1.socket tcp 套接字 2.http協議的請求相應格式 3.執行緒併發的建立方法 4.類的基本使用
#!usr/bin/env python3
# coding=utf-8
'''
1.多執行緒併發
2.可以請求簡單資料
3.能進行簡單請求分析
4.結構使用類進行封裝
'''
from socket import *
from threading import Thread
import sys
import traceback
# HTTPserver類,封裝具體的伺服器功能
class HttpServer(object):
def __init__(self, server_addr, static_dir):
# 增添伺服器物件屬性
self.server_address = server_addr
self.static_dir = static_dir # 我的靜態頁面儲存目錄
self.ip = server_addr[0] # 地址
self.port = server_addr[1] # 埠
# 建立套接字
self.create_socket()
def create_socket(self):
self.sockfd = socket()
self.sockfd.setsockopt(SOL_SOCKET, SO_REUSEADDR, 1) # 釋放埠
self.sockfd.bind(self.server_address) # 連線
def serve_forever(self):
self.sockfd.listen(5)
print('Listen the port %d' % self.port)
while True:
try:
connfd, addr = self.sockfd.accept()
except KeyboardInterrupt:
self.sockfd.close()
sys.exit('伺服器退出')
except Exception:
traceback.print_exc()
continue
# 建立新的執行緒處理請求
clientThread = Thread(target=self.handleRequest,
args=(connfd,))
clientThread.setDaemon(True)
clientThread.start()
# 客戶端請求函式
def handleRequest(self, connfd):
# 接收客戶端請求
request = connfd.recv(4096)
# 解析請求內容
requestHeaders = request.splitlines()
print(connfd.getpeername(), ":", requestHeaders[0])
# 獲取具體請求內容
getRequest = str(requestHeaders[0]).split(' ')[1]
if getRequest == '/' or getRequest[-5:] == './html':
self.get_html(connfd, getRequest)
else:
self.get_data(connfd, getRequest)
connfd.close()
def get_html(self, connfd, getRequest):
if getRequest == '/':
filename = self.static_dir + '/index.html'
else:
filename = self.static_dir + getRequest
try:
f = open(filename)
except Exception:
# 沒有找到網頁
responseHeaders = 'HTTP/1.1 404 NOT FOUND\r\n'
responseHeaders += '\r\n'
responseBody = 'sorry,not found the page'
else:
responseHeaders = 'HTTP/1.1 200 OK\r\n'
responseHeaders += '\r\n'
responseBody = f.read()
finally:
response = responseHeaders + responseBody
connfd.send(response.encode())
def get_data(self, connfd, getRequest):
urls = ['/time', '/tedu', '/python']
if getRequest in urls:
responseHeaders = 'HTTP/1.1 200 OK\r\n'
responseHeaders += '\r\n'
if getRequest == '/time':
import time
responseBody = time.ctime()
elif getRequest == '/tedu':
responseBody = 'welcome to tarena'
elif getRequest == '/python':
responseBody = '人生苦短我用Python'
else:
responseHeaders = 'HTTP/1.1 404 NOT FOUND\r\n'
responseHeaders += '\r\n'
responseBody = 'sorry,not found the page'
response = responseHeaders + responseBody
connfd.send(response.encode())
if __name__ == "__main__":
# 伺服器IP
server_addr = ('0.0.0.0', 8888)
# 我的靜態頁面儲存目錄
static_dir = './static'
# 生成物件
httpd = HttpServer(server_addr, static_dir)
# 啟動伺服器
httpd.serve_forever()