1. 程式人生 > >pythonweb服務器編程(四)

pythonweb服務器編程(四)

服務 新的 動態數據 spl ces nvi time() span seh

Web動態服務器-1

#coding=utf-8
import socket
import sys
from multiprocessing import Process
import re

class WSGIServer(object):

    addressFamily = socket.AF_INET
    socketType = socket.SOCK_STREAM
    requestQueueSize = 5

    def __init__(self, serverAddress):
        #創建一個tcp套接字
        self.listenSocket = socket.socket(self.addressFamily,self.socketType)
        
#允許重復使用上次的套接字綁定的port self.listenSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1) #綁定 self.listenSocket.bind(serverAddress) #變為被動,並制定隊列的長度 self.listenSocket.listen(self.requestQueueSize) self.servrName = "localhost" self.serverPort
= serverAddress[1] def serveForever(self): 循環運行web服務器,等待客戶端的鏈接並為客戶端服務 while True: #等待新客戶端到來 self.clientSocket, client_address = self.listenSocket.accept() #方法2,多進程服務器,並發服務器於多個客戶端 newClientProcess = Process(target = self.handleRequest) newClientProcess.start()
#因為創建的新進程中,會對這個套接字+1,所以需要在主進程中減去依次,即調用一次close self.clientSocket.close() def setApp(self, application): 設置此WSGI服務器調用的應用程序入口函數 self.application = application def handleRequest(self): 用一個新的進程,為一個客戶端進行服務 self.recvData = self.clientSocket.recv(2014) requestHeaderLines = self.recvData.splitlines() for line in requestHeaderLines: print(line) httpRequestMethodLine = requestHeaderLines[0] getFileName = re.match("[^/]+(/[^ ]*)", httpRequestMethodLine).group(1) print("file name is ===>%s"%getFileName) #for test if getFileName[-3:] != ".py": if getFileName == /: getFileName = documentRoot + "/index.html" else: getFileName = documentRoot + getFileName print("file name is ===2>%s"%getFileName) #for test try: f = open(getFileName) except IOError: responseHeaderLines = "HTTP/1.1 404 not found\r\n" responseHeaderLines += "\r\n" responseBody = "====sorry ,file not found====" else: responseHeaderLines = "HTTP/1.1 200 OK\r\n" responseHeaderLines += "\r\n" responseBody = f.read() f.close() finally: response = responseHeaderLines + responseBody self.clientSocket.send(response) self.clientSocket.close() else: #根據接收到的請求頭構造環境變量字典 env = {} #調用應用的相應方法,完成動態數據的獲取 bodyContent = self.application(env, self.startResponse) #組織數據發送給客戶端 self.finishResponse(bodyContent) def startResponse(self, status, response_headers): serverHeaders = [ (Date, Tue, 31 Mar 2016 10:11:12 GMT), (Server, WSGIServer 0.2), ] self.headers_set = [status, response_headers + serverHeaders] def finishResponse(self, bodyContent): try: status, response_headers = self.headers_set #response的第一行 response = HTTP/1.1 {status}\r\n.format(status=status) #response的其他頭信息 for header in response_headers: response += {0}: {1}\r\n.format(*header) #添加一個換行,用來和body進行分開 response += \r\n #添加發送的數據 for data in bodyContent: response += data self.clientSocket.send(response) finally: self.clientSocket.close() #設定服務器的端口 serverAddr = (HOST, PORT) = ‘‘, 8888 #設置服務器靜態資源的路徑 documentRoot = ./html #設置服務器動態資源的路徑 pythonRoot = ./wsgiPy def makeServer(serverAddr, application): server = WSGIServer(serverAddr) server.setApp(application) return server def main(): if len(sys.argv) < 2: sys.exit(請按照要求,指定模塊名稱:應用名稱,例如 module:callable) #獲取module:callable appPath = sys.argv[1] #根據冒號切割為module和callable module, application = appPath.split(:) #添加路徑套sys.path sys.path.insert(0, pythonRoot) #動態導入module變量中指定的模塊 module = __import__(module) #獲取module變量中指定的模塊的,application變量指定的屬性 application = getattr(module, application) httpd = makeServer(serverAddr, application) print(WSGIServer: Serving HTTP on port %d ...\n%PORT) httpd.serveForever() if __name__ == __main__: main()

應用程序示例

mport time

def app(environ, start_response):
    status = 200 OK
    response_headers = [(Content-Type, text/plain)]
    start_response(status, response_headers)
    return [str(environ)+==Hello world from a simple WSGI application!--->%s\n%time.ctime()]

Web動態服務器-2-傳遞數據給應用

#coding=utf-8
import socket
import sys
from multiprocessing import Process
import re

class WSGIServer(object):

    addressFamily = socket.AF_INET
    socketType = socket.SOCK_STREAM
    requestQueueSize = 5

    def __init__(self, serverAddress):
        #創建一個tcp套接字
        self.listenSocket = socket.socket(self.addressFamily,self.socketType)
        #允許重復使用上次的套接字綁定的port
        self.listenSocket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        #綁定
        self.listenSocket.bind(serverAddress)
        #變為被動,並制定隊列的長度
        self.listenSocket.listen(self.requestQueueSize)

        self.servrName = "localhost"
        self.serverPort = serverAddress[1]

    def serveForever(self):
        循環運行web服務器,等待客戶端的鏈接並為客戶端服務
        while True:
            #等待新客戶端到來
            self.clientSocket, client_address = self.listenSocket.accept()

            #方法2,多進程服務器,並發服務器於多個客戶端
            newClientProcess = Process(target = self.handleRequest)
            newClientProcess.start()

            #因為創建的新進程中,會對這個套接字+1,所以需要在主進程中減去依次,即調用一次close
            self.clientSocket.close()

    def setApp(self, application):
        設置此WSGI服務器調用的應用程序入口函數
        self.application = application

    def handleRequest(self):
        用一個新的進程,為一個客戶端進行服務
        self.recvData = self.clientSocket.recv(2014)
        requestHeaderLines = self.recvData.splitlines()
        for line in requestHeaderLines:
            print(line)

        httpRequestMethodLine = requestHeaderLines[0]
        getFileName = re.match("[^/]+(/[^ ]*)", httpRequestMethodLine).group(1)
        print("file name is ===>%s"%getFileName) #for test

        if getFileName[-3:] != ".py":

            if getFileName == /:
                getFileName = documentRoot + "/index.html"
            else:
                getFileName = documentRoot + getFileName

            print("file name is ===2>%s"%getFileName) #for test

            try:
                f = open(getFileName)
            except IOError:
                responseHeaderLines = "HTTP/1.1 404 not found\r\n"
                responseHeaderLines += "\r\n"
                responseBody = "====sorry ,file not found===="
            else:
                responseHeaderLines = "HTTP/1.1 200 OK\r\n"
                responseHeaderLines += "\r\n"
                responseBody = f.read()
                f.close()
            finally:
                response = responseHeaderLines + responseBody
                self.clientSocket.send(response)
                self.clientSocket.close()
        else:
            #處理接收到的請求頭
            self.parseRequest()

            #根據接收到的請求頭構造環境變量字典
            env = self.getEnviron()

            #調用應用的相應方法,完成動態數據的獲取
            bodyContent = self.application(env, self.startResponse)

            #組織數據發送給客戶端
            self.finishResponse(bodyContent)

    def parseRequest(self):
        提取出客戶端發送的request
        requestLine = self.recvData.splitlines()[0]
        requestLine = requestLine.rstrip(\r\n)
        self.requestMethod, self.path, self.requestVersion = requestLine.split(" ")

    def getEnviron(self):
        env = {}
        env[wsgi.version]      = (1, 0)
        env[wsgi.input]        = self.recvData
        env[REQUEST_METHOD]    = self.requestMethod    # GET
        env[PATH_INFO]         = self.path             # /index.html
        return env

    def startResponse(self, status, response_headers, exc_info=None):
        serverHeaders = [
            (Date, Tue, 31 Mar 2016 10:11:12 GMT),
            (Server, WSGIServer 0.2),
        ]
        self.headers_set = [status, response_headers + serverHeaders]

    def finishResponse(self, bodyContent):
        try:
            status, response_headers = self.headers_set
            #response的第一行
            response = HTTP/1.1 {status}\r\n.format(status=status)
            #response的其他頭信息
            for header in response_headers:
                response += {0}: {1}\r\n.format(*header)
            #添加一個換行,用來和body進行分開
            response += \r\n
            #添加發送的數據
            for data in bodyContent:
                response += data

            self.clientSocket.send(response)
        finally:
            self.clientSocket.close()

#設定服務器的端口
serverAddr = (HOST, PORT) = ‘‘, 8888
#設置服務器靜態資源的路徑
documentRoot = ./html
#設置服務器動態資源的路徑
pythonRoot = ./wsgiPy

def makeServer(serverAddr, application):
    server = WSGIServer(serverAddr)
    server.setApp(application)
    return server

def main():

    if len(sys.argv) < 2:
        sys.exit(請按照要求,指定模塊名稱:應用名稱,例如 module:callable)

    #獲取module:callable
    appPath = sys.argv[1]
    #根據冒號切割為module和callable
    module, application = appPath.split(:)
    #添加路徑套sys.path
    sys.path.insert(0, pythonRoot)
    #動態導入module變量中指定的模塊
    module = __import__(module)
    #獲取module變量中制定的模塊的application變量指定的屬性
    application = getattr(module, application)
    httpd = makeServer(serverAddr, application)
    print(WSGIServer: Serving HTTP on port {port} ...\n.format(port=PORT))
    httpd.serveForever()

if __name__ == __main__:
    main()

技術分享圖片

pythonweb服務器編程(四)