Python实现简易Web服务器

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服务器的更多相关文章
- python 启动简单web服务器
有时我们在开发web静态页面时,需要一个web服务器来测试. 这时可以利用python提供的web服务器来实现. 1.在命令行下进入某个目录 2.在该目录下运行命令: python -m Simple ...
- Python实现简易HTTP服务器
一.Python3 搭建简易HTTP服务器 python -m http.server 浏览器访问:http://localhost:8000 Python3 cgiserver python -m ...
- 用python快速搭建WEB服务器
cmd下进入你要搞WEB项目的目录 输入↓方代码 python -m SimpleHTTPServer 端口号# 默认是8000 这样就启动了一个简单的WEB服务器
- [js高手之路]node js系列课程-创建简易web服务器与文件读写
web服务器至少有以下几个特点: 1.24小时不停止的工作,也就是说这个进程要常驻在内存中 2.24小时在某一端口监听,如: http://localhost:8080, www服务器默认端口80 3 ...
- 利用Python实现对Web服务器的目录探测
今天是一篇提升技能的干货分享,操作性较强,适用于中级水平的小伙伴,文章阅读用时约3分钟. PART 1/Python Python是一种解释型.面向对象.动态数据类型的高级程序设计语言. Python ...
- 利用 python 实现对web服务器的目录探测
一.pythonPython是一种解释型.面向对象.动态数据类型的高级程序设计语言.python 是一门简单易学的语言,并且功能强大也很灵活,在渗透测试中的应用广泛,让我们一起打造属于自己的渗透测试工 ...
- 手写简易WEB服务器
今天我们来写一个类似于Tomcat的简易服务器.可供大家深入理解一下tomcat的工作原理,本文仅供新手参考,请各位大神指正!首先我们要准备的知识是: Socket编程 HTML HTTP协议 服务器 ...
- 基于python实现简单web服务器
做web开发的你,真的熟悉web服务器处理机制吗? 分析请求数据 下面是一段原始的请求数据: b'GET / HTTP/1.1\r\nHost: 127.0.0.1:8000\r\nConnectio ...
- python网络-动态Web服务器案例(30)
一.浏览器请求HTML页面的过程 了解了HTTP协议和HTML文档,其实就明白了一个Web应用的本质就是: 浏览器发送一个HTTP请求: 服务器收到请求,生成一个HTML文档: 服务器把HTML文档作 ...
随机推荐
- 队列详解及java实现
导读 栈和队列是有操作限制的线性表. 目录 1.队列的概念.特点.存储结构. 2.栈队列的java实现. 概念 队列是一种在一端进行插入,而在另一端进行删除的线性表.1.队列的插入端称为队尾:队列的删 ...
- R语言命令行参数
批量画图任务中,需要在R中传入若干参数,之前对做法是在perl中每一个任务建立一个Rscript,这种方式超级不cool,在群里学习到R的@ARGV调用方式,差不多能够达到批量任务的要求: a ...
- amaze UI 笔记 - JS
导航添加依据 http://amazeui.org/javascript 下面内容属学习笔记,如有理解偏差和错误请留言相告,感谢!* =(官网这块写的很详细) 一 .UI增强 1.警告框 显示可关闭的 ...
- mysql存储过程 详细注释
原文:https://my.oschina.net/u/3582142/blog/1581929
- 模拟winform里的控件的事件和委托机制
参考:.NET 中的委托 委托的两大用处 1.委托可以实现方法作为参数进行传递,如 /// <summary> /// the English speaker. /// </summ ...
- 一个InnoDB性能超过Oracle的调优Case
年前抽空到兄弟公司支援了一下Oracle迁移MySQL的测试,本想把MySQL调优到接近Oracle的性能即可,但经过 @何_登成 @淘宝丁奇 @淘宝褚霸 @淘伯松 诸位大牛的指导和帮助(排名不分先后 ...
- Qt5.3.1 OpenCV2.4.9 开发环境配置
首先是将我们需要的三个软件安装:分别是OpenCV2.4.9.QT5.3.1 .Cmake3.0.2 一定要使用Cmake3.0.2编译OpenCV2.4.9 其他版本的不一定能编译成功!!!! A. ...
- 解决Fiddler出现无线弹框 "creation of the root certificate was not successful”的问题
打开Fiddler 访问:http://localhost:8888/ 安装证书,如果提示没有证书(8888是你在Tool->Fiddler Option->Connections设置的F ...
- H5 调用手机摄像机、相册功能
<input type="file" accept="image/*" capture="camera"> <input ...
- vue路由对象($route)参数简介
路由对象在使用了 vue-router 的应用中,路由对象会被注入每个组件中,赋值为 this.$route ,并且当路由切换时,路由对象会被更新. so , 路由对象暴露了以下属性: 1.$rout ...