下面给大家介绍python实现简易版的web服务器,具体内容详情大家通过本文学习吧!
1、请自行了解HTTP协议
http://www.zzvips.com/article/94556.html(点击跳转)
2、创建Socket服务,监听指定IP和端口
3、以阻塞方式等待客户端连接
4、读取客户端请求数据并进行解析
5、准备服务器运行上下文
6、处理客户端请求数据
7、根据用户请求路径读取文件
8、返回响应结果给客户端
9、程序入口
10、目录结构
11、运行
1
|
python wsgiserver.py app:run
|
12、源码
a.wsgiserver.py文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
|
#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文件
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
|
#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服务器,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对服务器之家网站的支持!
原文链接:https://www.cnblogs.com/reboot51/p/8375979.html