前几天写了 浅谈cgi、wsgi、uwsgi 与 uWSGI 等一些 python web 开发中遇到的一些名词的理解,今天博主就根据 wsgi 标准实现一个 web server,并尝试用它来跑 Django、tornado 框架的 app。

编写一个简单的 http server

在实现 wsgi server 之前我们先要做一些准备工作。首先,http server 使用 http 协议,而 http 协议封装在 tcp 协议中,所以要建立一个 http server 我们先要建立一个 tcp server。要使用 tcp 协议我们不可能自己实现一个,现在比较流行的解决方案就是使用 socket 套接字编程, socket 已经帮我们实现了 tcp 协议的细节,我们可以直接拿来使用不用关心细节。 socket 编程是语言无关的,不管是以前博主用 MFC 写聊天室还是用 C# 写网络延迟计算还是现在写 http server,它的使用流程都是一样的:

server

  1. 初始化 socket;
  2. 绑定套接字到端口(bind);
  3. 监听端口(listen);
  4. 接受连接请求(accept);
  5. 通信(send/recv);
  6. 关闭连接(close);

client

  1. 初始化 socket;
  2. 发出连接请求(connect);
  3. 通信(send/recv);
  4. 关闭连接(close);

server 的具体实现:

1234567891011121314151617181920212223242526272829 # coding: utf-8# server.py import socket HOST, PORT = \’\’, 8888# 初始化listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)# 绑定listen_socket.bind((HOST, PORT))# 监听listen_socket.listen(1)print \’Serving HTTP on port %s …\’ % PORTwhile True:    # 接受请求    client_connection, client_address = listen_socket.accept()    # 通信    request = client_connection.recv(1024)    print request     http_response = \”\”\”HTTP/1.1 200 OK Hello, World!\”\”\”    client_connection.sendall(http_response)    # 关闭连接    client_connection.close()

而 client 不需要我们自己实现,我们的浏览器就是一个 client ,现在运行python server.py,然后在浏览器中打开 localhost:8888即可看到浏览器中显示 hello world!,这么快就实现了一个 http server 有木有 hin 激动!

然而想要 Django 这类框架的 app 在我们写的 http server 中运行起来还远远不够,现在我们就需要引入 wsgi 规范,根据这个规范我们就可以让自己的 server 也能运行这些框架的 app啦。

编写一个标准的 wsgi server

首先,我们要看官方文档里 wsgi 的解释:PEP 3333
嗯,就是一篇很长的英语阅读理解,大概意思就是如果你想让你的服务器和应用程序一起好好工作,你要遵循这个标准来写你的 web app 和 web server:

server–middleware–application

application

application 是一个接受接受两个参数environ, start_response的标准 wsgi app:

1234 environ:          一个包含请求信息及环境信息的字典,server 端会详细说明start_response:   一个接受两个参数`status, response_headers`的方法:status:           返回状态码,如http 200404response_headers: 返回信息头部列表

具体实现:

12345 def application(environ, start_response):    status = \’200 OK\’    response_headers = [(\’Content-Type\’, \’text/plain\’)]    start_response(status, response_headers)    return [\’Hello world\’]

这样一个标准的 wsgi app 就写好了,虽然这看上去和我们写的 Django app、 tornado app 大相径庭,但实际上这些 app 都会经过相应的处理来适配 wsgi 标准,这个之后会详谈。

server

wsgi server 的实现要复杂一些,所以我先贴自己实现的 wsgi server 代码,然后再讲解:

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647\” data-line=\”crayon-5812b1a33eb6d602158450-43\”>4344454647r 之前我们先要做一些准备工作。首先,http server 使用 http 协议,而 http 协议封装在 tcp 协议中,所以要建立一个 http server 我们先要建立一个 tcp server。要使用 tcp 协议我们不可能自己实现一个,现在比较流行的解决方案就是使用 socket 套接字编程, socket 已经帮我们实现了 tcp 协议的细节,我们可以直接拿来使用不用关心细节。 socket 编程是语言无关的,不管是以前博主用 MFC 写聊天室还是用 C# 写网络延迟计算还是现在写 http server,它的使用流程都是一样的:

server

  1. 初始化 socket;
  2. 绑定套接字到端口(bind);
  3. 监听端口(listen);
  4. 接受连接请求(accept);
  5. 通信(send/recv);
  6. 关闭连接(close);

client

  1. 初始化 socket;
  2. 发出连接请求(connect);
  3. 通信(send/recv);
  4. 关闭连接(close);

server 的具体实现:

1234567891011121314151617181920212223242526272829 # coding: utf-8# server.py import socket HOST, PORT = \’\’, 8888# 初始化listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)# 绑定listen_socket.bind((HOST, PORT))# 监听listen_socket.listen(1)print \’Serving HTTP on port %s …\’ % PORTwhile True:    # 接受请求    client_connection, client_address = listen_socket.accept()    # 通信    request = client_connection.recv(1024)    print request     http_response = \”\”\”HTTP/1.1 200 OK Hello, World!\”\”\”    client_connection.sendall(http_response)    # 关闭连接    client_connection.close()

而 client 不需要我们自己实现,我们的浏览器就是一个 client ,现在运行python server.py,然后在浏览器中打开 localhost:8888即可看到浏览器中显示 hello world!,这么快就实现了一个 http server 有木有 hin 激动!

然而想要 Django 这类框架的 app 在我们写的 http server 中运行起来还远远不够,现在我们就需要引入 wsgi 规范,根据这个规范我们就可以让自己的 server 也能运行这些框架的 app啦。

编写一个标准的 wsgi server

首先,我们要看官方文档里 wsgi 的解释:PEP 3333
嗯,就是一篇很长的英语阅读理解,大概意思就是如果你想让你的服务器和应用程序一起好好工作,你要遵循这个标准来写你的 web app 和 web server:

server–middleware–application

application

application 是一个接受接受两个参数environ, start_response的标准 wsgi app:

1234 environ:          一个包含请求信息及环境信息的字典,server 端会详细说明start_response:   一个接受两个参数`status, response_headers`的方法:status:           返回状态码,如http 200404response_headers: 返回信息头部列表

具体实现:

12345 def application(environ, start_response):    status = \’200 OK\’    response_headers = [(\’Content-Type\’, \’text/plain\’)]    start_response(status, response_headers)    return [\’Hello world\’]

这样一个标准的 wsgi app 就写好了,虽然这看上去和我们写的 Django app、 tornado app 大相径庭,但实际上这些 app 都会经过相应的处理来适配 wsgi 标准,这个之后会详谈。

server

wsgi server 的实现要复杂一些,所以我先贴自己实现的 wsgi server 代码,然后再讲解:

123456789101112131415161718192021222324252627282930313233