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文档作 ...
随机推荐
- centos虚拟机初始化脚本
功能 修改主机名为node. 网卡开机启动并设置ip为静态18.8 更新yum源为国内yum源,并安装vim lrzsz wget man ntpdate软件. 关闭iptables selinux, ...
- Java的虚方法
虚方法出现在Java的多态特性中, 父类与子类之间的多态性,对父类的函数进行重新定义.如果在子类中定义某方法与其父类有相同的名称和参数,我们说该方法被重写 (Overriding).在Java中,子类 ...
- 深入研究ES6 Generators
ES6 Generators系列: ES6 Generators基本概念 深入研究ES6 Generators ES6 Generators的异步应用 ES6 Generators并发 如果你还不知道 ...
- Java学习笔记5(类的入门以及ArrayList)
1.类的概念:将现实生活中的事物抽象成了代码(类),我们可以使用自定义的数组类型(类)来描述现实生活中的事物. 2.分析:用一部手机来分析,手机可以打电话,上网,听音乐,这些就是方法,手机有型号,颜色 ...
- SQL常用增删改查语句
1增 1.1[插入单行]insert [into] <表名> (列名) values (列值)例:insert into Strdents (姓名,性别,出生日期) values ('开心 ...
- Java程序员的C++回归路(一)
前言:工作后吃饭的语言是java,同时写一些python和js,在学习机器学习的时候发现有必要再熟悉一下c++,同时工作也有c++的使用需求.于是开始对照c++ primer自学,希望能够对同样是其他 ...
- Undefined symbols for architecture arm64(其cpu架构)
"_OBJC_CLASS_$_XXX",referenced from: 之类的问题,很多人看到这些很头疼,不知道从何下手去修改.以下是我总结的相关修改办法.如下图 这是一个很明显 ...
- es6的常用语法
最常用的ES6特性 let, const, class, extends, super, arrow functions, template string, destructuring, defaul ...
- 【整理】REACT一些自己感觉需要记的东西
REACT生命周期: 组件的生命周期可分成三个状态: Mounting:已插入真实 DOM Updating:正在被重新渲染 Unmounting:已移出真实 DOM 生命周期的方法有: compon ...
- 洛谷 P1914 小书童——密码【字符串+模拟】
P1914 小书童——密码 题目背景 某蒟蒻迷上了“小书童”,有一天登陆时忘记密码了(他没绑定邮箱or手机),于是便把问题抛给了神犇你. 题目描述 蒟蒻虽然忘记密码,但他还记得密码是由一串字母组成.且 ...