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

目录
相关文章
|
11月前
|
人工智能 JavaScript API
零基础构建MCP服务器:TypeScript/Python双语言实战指南
作为一名深耕技术领域多年的博主摘星,我深刻感受到了MCP(Model Context Protocol)协议在AI生态系统中的革命性意义。MCP作为Anthropic推出的开放标准,正在重新定义AI应用与外部系统的交互方式,它不仅解决了传统API集成的复杂性问题,更为开发者提供了一个统一、安全、高效的连接框架。在过去几个月的实践中,我发现许多开发者对MCP的概念理解透彻,但在实际动手构建MCP服务器时却遇到了各种技术壁垒。从环境配置的细节问题到SDK API的深度理解,从第一个Hello World程序的调试到生产环境的部署优化,每一个环节都可能成为初学者的绊脚石。因此,我决定撰写这篇全面的实
2537 67
零基础构建MCP服务器:TypeScript/Python双语言实战指南
|
移动开发 数据挖掘 开发者
服务器发送事件(SSE)在现代Web开发中的关键作用
服务器发送事件(SSE)是HTML5标准协议,用于服务器主动向客户端推送实时数据,适合单向通信场景。相比WebSocket,SSE更简洁高效,基于HTTP协议,具备自动重连、事件驱动等特性。常见应用场景包括实时通知、新闻推送、数据分析等。通过Apipost等工具可轻松调试SSE,助力开发者构建高效实时Web应用。示例中,电商平台利用SSE实现秒杀活动通知,显著减少延迟并简化架构。掌握SSE技术,能大幅提升用户体验与开发效率。
|
移动开发 JavaScript 前端开发
精通服务器推送事件(SSE)与 Python 和 Go 实现实时数据流 🚀
服务器推送事件(SSE)是HTML5规范的一部分,允许服务器通过HTTP向客户端实时推送更新。相比WebSocket,SSE更轻量、简单,适合单向通信场景,如实时股票更新或聊天消息。它基于HTTP协议,使用`EventSource` API实现客户端监听,支持自动重连和事件追踪。虽然存在单向通信与连接数限制,但其高效性使其成为许多轻量级实时应用的理想选择。文中提供了Python和Go语言的服务器实现示例,以及HTML/JavaScript的客户端代码,帮助开发者快速集成SSE功能,提升用户体验。
|
10月前
|
人工智能 自然语言处理 安全
Python构建MCP服务器:从工具封装到AI集成的全流程实践
MCP协议为AI提供标准化工具调用接口,助力模型高效操作现实世界。
1681 1
|
Python
使用Python实现multipart/form-data文件接收的http服务器
至此,使用Python实现一个可以接收 'multipart/form-data' 文件的HTTP服务器的步骤就讲解完毕了。希望通过我的讲解,你可以更好地理解其中的逻辑,另外,你也可以尝试在实际项目中运用这方面的知识。
651 69
|
人工智能 安全 Shell
Jupyter MCP服务器部署实战:AI模型与Python环境无缝集成教程
Jupyter MCP服务器基于模型上下文协议(MCP),实现大型语言模型与Jupyter环境的无缝集成。它通过标准化接口,让AI模型安全访问和操作Jupyter核心组件,如内核、文件系统和终端。本文深入解析其技术架构、功能特性及部署方法。MCP服务器解决了传统AI模型缺乏实时上下文感知的问题,支持代码执行、变量状态获取、文件管理等功能,提升编程效率。同时,严格的权限控制确保了安全性。作为智能化交互工具,Jupyter MCP为动态计算环境与AI模型之间搭建了高效桥梁。
802 2
Jupyter MCP服务器部署实战:AI模型与Python环境无缝集成教程
|
11月前
|
安全 Linux 网络安全
Python极速搭建局域网文件共享服务器:一行命令实现HTTPS安全传输
本文介绍如何利用Python的http.server模块,通过一行命令快速搭建支持HTTPS的安全文件下载服务器,无需第三方工具,3分钟部署,保障局域网文件共享的隐私与安全。
2811 0
|
存储 监控 API
【Azure App Service】分享使用Python Code获取App Service的服务器日志记录管理配置信息
本文介绍了如何通过Python代码获取App Service中“Web服务器日志记录”的配置状态。借助`azure-mgmt-web` SDK,可通过初始化`WebSiteManagementClient`对象、调用`get_configuration`方法来查看`http_logging_enabled`的值,从而判断日志记录是否启用及存储方式(关闭、存储或文件系统)。示例代码详细展示了实现步骤,并附有执行结果与官方文档参考链接,帮助开发者快速定位和解决问题。
371 22
|
8月前
|
弹性计算 运维 安全
阿里云轻量应用服务器与云服务器ECS啥区别?新手帮助教程
阿里云轻量应用服务器适合个人开发者搭建博客、测试环境等低流量场景,操作简单、成本低;ECS适用于企业级高负载业务,功能强大、灵活可扩展。二者在性能、网络、镜像及运维管理上差异显著,用户应根据实际需求选择。
701 10

推荐镜像

更多