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