169 python网络编程 - Web动态服务器

简介: 169 python网络编程 - 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()

2. 应用程序示例

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

3.传递数据给应用

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

目录
相关文章
|
2月前
|
XML 前端开发 JavaScript
PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑
本文深入探讨了PHP与Ajax在Web开发中的交互技术。PHP作为服务器端脚本语言,处理数据和业务逻辑;Ajax则通过异步请求实现页面无刷新更新。文中详细介绍了两者的工作原理、数据传输格式选择、具体实现方法及实际应用案例,如实时数据更新、表单验证与提交、动态加载内容等。同时,针对跨域问题、数据安全与性能优化提出了建议。总结指出,PHP与Ajax的结合能显著提升Web应用的效率和用户体验。
56 3
|
2月前
|
Kubernetes 网络协议 Python
Python网络编程:从Socket到Web应用
在信息时代,网络编程是软件开发的重要组成部分。Python作为多用途编程语言,提供了从Socket编程到Web应用开发的强大支持。本文将从基础的Socket编程入手,逐步深入到复杂的Web应用开发,涵盖Flask、Django等框架的应用,以及异步Web编程和微服务架构。通过本文,读者将全面了解Python在网络编程领域的应用。
43 1
|
3月前
|
SQL 关系型数据库 数据库
优化Web开发流程:Python ORM的优势与实现细节
【10月更文挑战第4天】在Web开发中,数据库操作至关重要,但直接编写SQL语句既繁琐又易错。对象关系映射(ORM)技术应运而生,让开发者以面向对象的方式操作数据库,显著提升了开发效率和代码可维护性。本文探讨Python ORM的优势及其实现细节,并通过Django ORM的示例展示其应用。ORM提供高级抽象层,简化数据库操作,提高代码可读性,并支持多种数据库后端,防止SQL注入。Django内置强大的ORM系统,通过定义模型、生成数据库表、插入和查询数据等步骤,展示了如何利用ORM简化复杂的数据库操作。
75 6
|
3月前
|
Java PHP
PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。理解其垃圾回收机制有助于开发高效稳定的PHP应用。
【10月更文挑战第1天】PHP作为广受青睐的服务器端脚本语言,在Web开发中占据重要地位。其垃圾回收机制包括引用计数与循环垃圾回收,对提升应用性能和稳定性至关重要。本文通过具体案例分析,详细探讨PHP垃圾回收机制的工作原理,特别是如何解决循环引用问题。在PHP 8中,垃圾回收机制得到进一步优化,提高了效率和准确性。理解这些机制有助于开发高效稳定的PHP应用。
56 3
|
4月前
|
数据安全/隐私保护
Haskell网络编程:代理服务器的高级使用技巧
Haskell网络编程:代理服务器的高级使用技巧
|
4月前
|
安全 API 开发者
Web 开发新风尚!Python RESTful API 设计与实现,让你的接口更懂开发者心!
在当前的Web开发中,Python因能构建高效简洁的RESTful API而备受青睐,大大提升了开发效率和用户体验。本文将介绍RESTful API的基本原则及其在Python中的实现方法。以Flask为例,演示了如何通过不同的HTTP方法(如GET、POST、PUT、DELETE)来创建、读取、更新和删除用户信息。此示例还包括了基本的路由设置及操作,为开发者提供了清晰的API交互指南。
120 6
|
4月前
|
网络协议 Python
告别网络编程迷雾!Python Socket编程基础与实战,让你秒变网络达人!
在网络编程的世界里,Socket编程是连接数据与服务的关键桥梁。对于初学者,这往往是最棘手的部分。本文将用Python带你轻松入门Socket编程,从创建TCP服务器与客户端的基础搭建,到处理并发连接的实战技巧,逐步揭开网络编程的神秘面纱。通过具体的代码示例,我们将掌握Socket的基本概念与操作,让你成为网络编程的高手。无论是简单的数据传输还是复杂的并发处理,Python都能助你一臂之力。希望这篇文章成为你网络编程旅程的良好开端。
66 3
|
4月前
|
SQL 缓存 数据库
构建高效Web应用:掌握Python中的ORM映射技术
在Web开发中,数据库操作至关重要,但直接编写SQL语句会增加代码复杂度并降低效率。对象关系映射(ORM)技术通过将对象模型映射为数据库表,使开发者能以面向对象的方式处理数据,提升开发效率和代码可维护性。本文以Python和SQLAlchemy为例,介绍ORM的基本概念、安装方法及使用技巧,并展示其在提升Web应用性能方面的优势。通过ORM,开发者可以简化数据库操作,专注于业务逻辑实现,提高开发效率和代码质量。
59 1
|
4月前
|
网络协议 开发者 Python
网络编程小白秒变大咖!Python Socket基础与进阶教程,轻松上手无压力!
在网络技术飞速发展的今天,掌握网络编程已成为开发者的重要技能。本文以Python为工具,带你从Socket编程基础逐步深入至进阶领域。首先介绍Socket的概念及TCP/UDP协议,接着演示如何用Python创建、绑定、监听Socket,实现数据收发;最后通过构建简单的聊天服务器,巩固所学知识。让初学者也能迅速上手,成为网络编程高手。
85 1
|
4月前
|
SQL 安全 JavaScript
告别Web安全小白!Python实战指南:抵御SQL注入、XSS、CSRF的秘密武器!
【9月更文挑战第12天】在Web开发中,安全漏洞如同暗礁,尤其对初学者而言,SQL注入、跨站脚本(XSS)和跨站请求伪造(CSRF)是常见挑战。本文通过实战案例,展示如何利用Python应对这些威胁。首先,通过参数化查询防止SQL注入;其次,借助Jinja2模板引擎自动转义机制抵御XSS攻击;最后,使用Flask-WTF库生成和验证CSRF令牌,确保转账功能安全。掌握这些技巧,助你构建更安全的Web应用。
75 5