import socket
from multiprocessing import Process
import re
class HTTPServer(object):
def __init__(self, application):
self.server_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
self.app = application
def bind(self, port):
print('port:',port)
self.server_socket.bind(('', port))
def start(self):
self.server_socket.listen(128)
print('HTTP server is running...')
while True:
conn_socket, client_addr = self.server_socket.accept()
print('connection from %s : %s' % client_addr)
# 创建新进程处理客户端连接
p = Process(target = self.handle_request, args = (conn_socket,))
p.start()
conn_socket.close()
def start_response(self, status, headers):
server_headers = [
('Server', 'MyWebServer 1.0')
]
server_headers = headers + server_headers
# 构造响应首部行
response_headers = 'HTTP/1.1 ' + status + '\r\n'
for header in server_headers:
response_headers = response_headers + '%s:%s' % header + '\r\n'
self.response_headers = response_headers
def handle_request(self, conn_socket):
'''处理客户端请求'''
env = {}
request_data = conn_socket.recv(2048).decode('utf-8')
print('request from client:')
print(request_data)
'''解析请求返回响应'''
# 请求行
reuqestmethodline = request_data.split('\r\n')[0]
# 请求方法
requestmethod = reuqestmethodline.split(' ', 1)[0]
# 请求资源
requestpath = re.match(r'\w+\s+(/[a-zA-Z0-9\_\.]*)',reuqestmethodline).group(1)
env['Method'] = requestmethod
env['PATH_INFO'] = requestpath
# 返回响应体
response_body = self.app(env, self.start_response)
response = self.response_headers + '\r\n' + response_body
print('response from server:')
print(response)
conn_socket.send(response.encode('utf-8'))
conn_socket.close()
import time
from mywebserver import HTTPServer
class Application(object):
# 框架的核心部分
def __init__(self, urls):
self.urls = urls
def __call__(self, env, start_response):
path = env.get('PATH_INFO', '/')
for url, handler in self.urls:
if path == url:
response_body = handler(env, start_response)
return response_body
# 请求路径不存在,返回 404 响应码
status = '404 Not Found'
headers = [('Content-Type', 'text/html')]
start_response(status, headers)
response_body = 'The file not found!'
return response_body
def ctime(env, start_response):
status = '200 OK'
headers = [('Content-Type', 'text/html')]
start_response(status, headers)
return time.ctime()
def hello(env, start_response):
status = '200 OK'
headers = [('Content-Type', 'text/html')]
start_response(status, headers)
return 'Hello, World!'
urls = [
('/', hello),
('/ctime', ctime),
('/hello', hello)
]
app = Application(urls)
http_server = HTTPServer(app)
http_server.bind(8000)
http_server.start()
λ python mywebframe.py
port: 8000
HTTP server is running...
connection from 127.0.0.1 : 50094
connection from 127.0.0.1 : 50095
port: 8000
Traceback (most recent call last):
File "<string>", line 1, in <module>
File "C:\Users\taomian\AppData\Local\Programs\Python\Python35\lib\multiprocessing\spawn.py", line 106, in spawn_main
exitcode = _main(fd)
File "C:\Users\taomian\AppData\Local\Programs\Python\Python35\lib\multiprocessing\spawn.py", line 115, in _main
prepare(preparation_data)
File "C:\Users\taomian\AppData\Local\Programs\Python\Python35\lib\multiprocessing\spawn.py", line 226, in prepare
_fixup_main_from_path(data['init_main_from_path'])
File "C:\Users\taomian\AppData\Local\Programs\Python\Python35\lib\multiprocessing\spawn.py", line 278, in _fixup_main_from_path
run_name="__mp_main__")
File "C:\Users\taomian\AppData\Local\Programs\Python\Python35\lib\runpy.py", line 254, in run_path
pkg_name=pkg_name, script_name=fname)
File "C:\Users\taomian\AppData\Local\Programs\Python\Python35\lib\runpy.py", line 96, in _run_module_code
mod_name, mod_spec, pkg_name, script_name)
File "C:\Users\taomian\AppData\Local\Programs\Python\Python35\lib\runpy.py", line 85, in _run_code
exec(code, run_globals)
File "D:\Documents\python\code\2.2 wsgi_server\mywebframe.py", line 40, in <module>
port: 8000
http_server.bind(8000)
Traceback (most recent call last):
File "D:\Documents\python\code\2.2 wsgi_server\mywebserver.py", line 11, in bind
File "<string>", line 1, in <module>
File "C:\Users\taomian\AppData\Local\Programs\Python\Python35\lib\multiprocessing\spawn.py", line 106, in spawn_main
self.server_socket.bind(('', port))
OSError: [WinError 10048] 通常每个套接字地址(协议 /网络地址 /端口)只允许使用一次。
allen@ubuntu:~/test/code$ python3 mywebframe.py
port: 8000
HTTP server is running...
connection from 127.0.0.1 : 45618
request from client:
GET / HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
Upgrade-Insecure-Requests: 1
response from server:
HTTP/1.1 200 OK
Content-Type:text/html
Server:MyWebServer 1.0
Hello, World!
connection from 127.0.0.1 : 45620
request from client:
GET /favicon.ico HTTP/1.1
Host: 127.0.0.1:8000
User-Agent: Mozilla/5.0 (X11; Ubuntu; Linux x86_64; rv:60.0) Gecko/20100101 Firefox/60.0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-GB,en;q=0.5
Accept-Encoding: gzip, deflate
Connection: keep-alive
response from server:
HTTP/1.1 404 Not Found
Content-Type:text/html
Server:MyWebServer 1.0
The file not found!
这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。
V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。
V2EX is a community of developers, designers and creative people.