1、请自行了解HTTP协议

http://www.cnblogs.com/reboot51/p/8358129.html(点击跳转)

2、创建Socket服务,监听指定IP和端口

3、以阻塞方式等待客户端连接

4、读取客户端请求数据并进行解析

5、准备服务器运行上下文

6、处理客户端请求数据

7、根据用户请求路径读取文件

8、返回响应结果给客户端

9、程序入口

10、目录结构

11、运行

python wsgiserver.py app:run

12、源码

a.wsgiserver.py文件

#encoding:utf-8

import socket
import StringIO
import sys
import logging
from datetime import datetime

logger = logging.getLogger(__name__)

class WSGIServer(object):

    address_family = socket.AF_INET
    socket_type = socket.SOCK_STREAM
    request_queue_size = 30
    recv_size = 1024

    def __init__(self, server_address):
        self._listen_socket = _listen_socket = socket.socket(self.address_family,
                                                         self.socket_type)       _listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR,1)       _listen_socket.bind(server_address)
       _listen_socket.listen(self.request_queue_size)
       _host, _port = _listen_socket.getsockname()
        self._server_name = socket.getfqdn(_host)
        self._server_port = _port
        self._headers_set = []
        self._application = None
        self._client = None
        self._request_data = None
        self._request_method = None
        self._path = None
        self._request_version = None
        self._start_response = None

    def set_application(self, application):
        self._application = application

    def server_forever(self):
        _listen_socket = self._listen_socket
        logger.info('listen on %s:%s', self._server_name, self._server_port)      while 1:
            try:
                self._client, _addr = _listen_socket.accept()
                self._handle_request(_addr)
            except KeyboardInterrupt as e:
                logger.info('interrupt')
                break
            except BaseException as e:
                logger.error(e)

    def _handle_request(self, client_addr):
        self._request_data = _request_data = self._client.recv(self.recv_size)
        self._parse_request_data(_request_data)
        _env = self._get_environment(client_addr)
        _result = self._application(_env, self.start_response)
        self._finish_response(_result)

    def _parse_request_data(self, request_data):
        _request_line = str(request_data.splitlines()[0]).rstrip('\r\n')
        (self._request_method, self._path, self._request_version) = _request_line.split()

    def _get_environment(self, client_addr):
        _env = {}
        _env['wsgi.version'] = (1, 0)
        _env['wsgi.url_scheme'] = 'http'
        _env['wsgi.input'] = StringIO.StringIO(self._request_data)                _env['wsgi.errors'] = sys.stderr
        _env['wsgi.multithread'] = False
        _env['wsgi.multiprocess'] = False
        _env['wsgi.run_once'] = False
        _env['REQUEST_METHOD'] = self._request_method.upper()
        _env['PATH_INFO'] = self._path
        _env['SERVER_NAME'] = self._server_name
        _env['SERVER_PORT'] = self._server_port
        _env['HTTP_CLIENT_IP'] = client_addr[0]

        logger.info('%s %s %s %s', _env['HTTP_CLIENT_IP'], datetime.now().strftime('%Y-%m-%d %H:%M:%S'), _env['REQUEST_METHOD'], _env['PATH_INFO'])

        return _env

    def start_response(self, status, response_headers, exc_info=None):            _server_headers = [
            ('Date', 'Sun, 7 Jun 2015 23:07:04 GMT'),
            ('Server', 'WSGIServer 0.1')
            ]
        self._headers_set = [status, response_headers + _server_headers]

    def _finish_response(self, result):
        _status, _response_headers = self._headers_set
        _response = 'HTTP/1.1 {status}\r\n'.format(status=_status)                for _header in _response_headers:
        _response += '{0}:{1}\r\n'.format(*_header)
        _response += '\r\n'
        for _data in result:
            _response += _data

        self._client.sendall(_response)
        self._client.close()

def make_server(server_address, application):
    server = WSGIServer(server_address)
    server.set_application(application)
    return server

if __name__ == '__main__':
    logging.basicConfig(level=logging.DEBUG)

    server_addr= ('0.0.0.0', 43002)

    app_path = sys.argv[1]
    module, application = app_path.split(':')
    module = __import__(module)
    application = getattr(module, application)
    httpd = make_server(server_addr, application)
    httpd.server_forever()

b.app.py文件

#encoding:utf-8

import os

class PageNotFoundException(BaseException):
    pass

def render(filename, dirname='html'):
    _path = os.path.join(dirname, filename)
    if os.path.exists(_path):
       with open(_path, 'rb') as handler:
           return handler.read()

   raise PageNotFoundException('file not found:%s' % _path)

def run(env, start_response):
    _path = env.get('PATH_INFO')
    response = ''
    try:
        _path = 'index.html' if _path == '/' else _path[1:]
        if _path.endswith('.css'):
            start_response('200 OK', [('Content-Type', 'text/css')])
        elif _path.endswith('.js'):
           start_response('200 OK', [('Content-Type', 'text/javascript')]
        elif _path.endswith('.html'):
            start_response('200 OK', [('Content-Type', 'text/html')])
        else:
            start_response('200 OK', [('Content-Type', 'text/plain'), ('Content-Disposition', 'attachment; filename=%s' % os.path.basename(_path))])
        response = render(_path)
    except PageNotFoundException as e:
        response = render('404.html')    

    return [response, '\r\n']

Python实现简易Web服务器的更多相关文章

  1. python 启动简单web服务器

    有时我们在开发web静态页面时,需要一个web服务器来测试. 这时可以利用python提供的web服务器来实现. 1.在命令行下进入某个目录 2.在该目录下运行命令: python -m Simple ...

  2. Python实现简易HTTP服务器

    一.Python3 搭建简易HTTP服务器 python -m http.server 浏览器访问:http://localhost:8000 Python3 cgiserver python -m  ...

  3. 用python快速搭建WEB服务器

    cmd下进入你要搞WEB项目的目录 输入↓方代码 python -m SimpleHTTPServer 端口号# 默认是8000 这样就启动了一个简单的WEB服务器

  4. [js高手之路]node js系列课程-创建简易web服务器与文件读写

    web服务器至少有以下几个特点: 1.24小时不停止的工作,也就是说这个进程要常驻在内存中 2.24小时在某一端口监听,如: http://localhost:8080, www服务器默认端口80 3 ...

  5. 利用Python实现对Web服务器的目录探测

    今天是一篇提升技能的干货分享,操作性较强,适用于中级水平的小伙伴,文章阅读用时约3分钟. PART 1/Python Python是一种解释型.面向对象.动态数据类型的高级程序设计语言. Python ...

  6. 利用 python 实现对web服务器的目录探测

    一.pythonPython是一种解释型.面向对象.动态数据类型的高级程序设计语言.python 是一门简单易学的语言,并且功能强大也很灵活,在渗透测试中的应用广泛,让我们一起打造属于自己的渗透测试工 ...

  7. 手写简易WEB服务器

    今天我们来写一个类似于Tomcat的简易服务器.可供大家深入理解一下tomcat的工作原理,本文仅供新手参考,请各位大神指正!首先我们要准备的知识是: Socket编程 HTML HTTP协议 服务器 ...

  8. 基于python实现简单web服务器

    做web开发的你,真的熟悉web服务器处理机制吗? 分析请求数据 下面是一段原始的请求数据: b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8000\r\nConnectio ...

  9. python网络-动态Web服务器案例(30)

    一.浏览器请求HTML页面的过程 了解了HTTP协议和HTML文档,其实就明白了一个Web应用的本质就是: 浏览器发送一个HTTP请求: 服务器收到请求,生成一个HTML文档: 服务器把HTML文档作 ...

随机推荐

  1. 物流包裹一站式查询(TrackingMore)

    快递查询接口 目前提供快递查询的接口平台有: Trackingmore 快递100 快递网 不同接口的区别: (1)Trackingmore支持380家快递公司,其中有55家为国内的快递,其余325家 ...

  2. sqlalchemy 踩过的坑

    记录下Sqlalchemy遇到的问题,不定时更新. 设置主键为非自增 sqlalchemy 在sql server中默认主键是自增的,如果在数据库设置的主键不是自增的,这个时候插入就会出现异常: 提示 ...

  3. Netty对Protocol Buffer多协议的支持(八)

    Netty对Protocol Buffer多协议的支持(八) 一.背景 在上篇博文中笔者已经用代码演示了如何在netty中使用Protocol Buffer,然而细心的用户可能会发现一个明显的不足之处 ...

  4. spring boot 之热部署(三)

    热部署:当发现程序修改时自动启动应用程序. spring boot使用的是spring-boot-devtools是一个为开发者服务的一个模块.其原理用了classLoader 其中一个加载不变的类, ...

  5. TurnipBit开发板“趣味赛”:平衡力大比拼

    让孩子在快乐自由的游戏中培养编程思维 平衡力大挑战是我们经常经常玩的的一个小游戏,脑补画面的话比较常见的是单腿平衡力大比拼,摇晃幅度小者胜利.游戏好玩归好玩,但是想要公平判断胜负却不容易.下面就教大家 ...

  6. JS 详解 Cookie、 LocalStorage 与 SessionStorage

    基本概念 Cookie Cookie 是小甜饼的意思.顾名思义,cookie 确实非常小,它的大小限制为4KB左右.它的主要用途有保存登录信息,比如你登录某个网站市场可以看到"记住密码&qu ...

  7. js 判断值为Array or Object的方法

    ①obj instanceof Array / Object ②Array.prototype.isPrototypeOf(obj) ③Object.prototype.toString.call(o ...

  8. tomcat配置https协议

    tomcat配置https协议 1.找到本地jdk底下的bin目录,bin目录底下存在文件keytool.exe(在bin目录下空白处,按住shift右击,打开命令窗口,如下图) 2.在cmd的命令窗 ...

  9. uboot引导linux内核过程详解【转】

    http://blog.chinaunix.net/uid-7828352-id-4472376.html 写的不错,尤其是uboot向linux内核传递参数的过程写的比较详细.

  10. 让你的Capslock键变废为宝

    Capslock 键的劣性 如果你是 Windows 系统用户,就会发现,很多时候我们是用不到 Capslock 键的.Capslock 键是切换大小写的锁定,而在平常工作中,只要摁住 Shift 键 ...