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!
1
taoing OP 在 win7 上看报错提示,我理解是端口 8000 被绑定了两次导致出错,不知道为什么会出现这种情况,想请教大佬可以给我解答。
|
2
ycfung 2018-05-21 20:05:32 +08:00 via Android
你这代码贴得太可怕了…
|
3
wwqgtxx 2018-05-21 20:05:47 +08:00
在 windows 下不要用“创建新进程处理客户端连接”这种方式,会出各种诡异的问题,应该使用“新线程”
|
4
wwqgtxx 2018-05-21 20:07:54 +08:00
另外这三行代码
http_server = HTTPServer(app) http_server.bind(8000) http_server.start() 应该包裹在 if __name__ == '__main__': 中,否则容易出现重复 start 你的 http_server 的情况 |
6
DevNet 2018-05-21 20:10:25 +08:00 via Android
可能是前一次运行已经占用了这个端口,然后一直没释放? kill 试试,
或者管理员权限问题? |
7
wwqgtxx 2018-05-21 20:10:38 +08:00
根本原因只在于 windows 不支持 fork 模式,他的 process 是重新起一个新的 Python.exe 实现的,所以会再次 import 一次你的 mywebframe.py,而不过你没有把启动代码包裹在 if __name__ == '__main__': 中就会导致这一段代码再一次在子进程中被执行
|
8
taoing OP @wwqgtxx 谢谢你的解答,原来系统间有差异,然后试了 if __name__ == '__main__':就没有报错了
|
9
iConnect 2018-05-21 20:21:55 +08:00 via Android
如果你生产环境是 Ubuntu,就不用管 win 上报错了,我们经理都要求所有人环境统一,减少系统差异带来额外的 bug
|
11
so1n 2018-05-21 21:04:16 +08:00 via Android
用 linux 吧,win 不能 fork 也没有 epoll 事件循环
|
12
lidongyx 2018-05-21 23:45:15 +08:00 via iPhone
学技术就不要在 windows 环境下折腾了,你折腾出来的这点经验都是浪费时间,因为生产实践中还是要用 linux 的,用虚拟机或者开发板、云服务器、双系统吧
|