1. 程式人生 > >Threading 的多執行緒併發

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()