翻译:Let's Build A Web Server.Part 3

我在 GitHub 上开源了这个系列文章的翻译版(还在跟进原作者的更新),第一次公开翻译英文教程,纯粹兴趣使然,错漏和不严谨在所难免……欢迎提出意见和建议。
? ? ?

原文:《Let’s Build A Web Server. Part 3.


“We learn most when we have to invent” —Piaget

Part 2 中,您创建了一个可以处理基本 HTTP GET 请求的简约 WSGI 服务器。我问你一个问题,“你怎么能让你的服务器一次处理多个请求?”,在本文中你会找到答案。因此,抓紧扶好,老司机带你飞。真的是老司机带你飞的感觉哦。准备好Linux,Mac OS X(或任何 * nix 系统)和 Python。文章中的所有源代码都可以在 GitHub 上找到。

首先让我们回想起一个非常基本的 Web 服务器是什么样的,以及服务器需要做些什么来服务客户端的请求。您在 Part 1Part 2 中创建的服务器是一个迭代服务器,一次处理一个客户端请求。在完成处理当前客户端请求之前,它不能接受新的客户端连接。有些客户可能对它不满意,因为他们必须排队等候,对于繁忙的服务器,这个等待队列可能会很长。
lsbaws_part3_it1

下面是迭代服务器 webserver3a.py 的代码:

#####################################################################
# Iterative server - webserver3a.py                                 #
#                                                                   #
# Tested with Python 2.7.9 & Python 3.4 on Ubuntu 14.04 & Mac OS X  #
#####################################################################
import socket

SERVER_ADDRESS = (HOST, PORT) = '', 8888
REQUEST_QUEUE_SIZE = 5


def handle_request(client_connection):
    request = client_connection.recv(1024)
    print(request.decode())
    http_response = b"""\
HTTP/1.1 200 OK

Hello, World!
"""
    client_connection.sendall(http_response)


def serve_forever():
    listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    listen_socket.bind(SERVER_ADDRESS)
    listen_socket.listen(REQUEST_QUEUE_SIZE)
    print('Serving HTTP on port {port} ...'.format(port=PORT))

    while True:
        client_connection, client_address = listen_socket.accept()
        handle_request(client_connection)
        client_connection.close()

if __name__ == '__main__':
    serve_forever()

译者注:原作者还没有更新 Part 3 的代码,所以这部分的代码我暂时没有自己验证,等待原作者的更新吧。。

想要观察这个服务器一次只处理一个客户端请求的情况,可以稍微修改服务器代码,在它向客户端发送响应后添加 60 秒的延迟。只需更改一行代码告诉服务器进程休眠60秒。

lsbaws_part3_it2

这是睡眠服务器 webserver3b.py 的代码:

#########################################################################
# Iterative server - webserver3b.py                                     #
#                                                                       #
# Tested with Python 2.7.9 & Python 3.4 on Ubuntu 14.04 & Mac OS X      #
#                                                                       #
# - Server sleeps for 60 seconds after sending a response to a client   #
#########################################################################
import socket
import time

SERVER_ADDRESS = (HOST, PORT) = '', 8888
REQUEST_QUEUE_SIZE = 5


def handle_request(client_connection):
    request = client_connection.recv(1024)
    print(request.decode())
    http_response = b"""\
HTTP/1.1 200 OK

Hello, World!
"""
    client_connection.sendall(http_response)
    time.sleep(60)  # 休眠并阻塞进程60秒钟


def serve_forever():
    listen_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
    listen_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
    listen_socket.bind(SERVER_ADDRESS)
    listen_socket.listen(REQUEST_QUEUE_SIZE)
    print('Serving HTTP on port {port} ...'.format(port=PORT))

    while True:
        client_connection, client_address = listen_socket.accept()
        handle_request(client_connection)
        client_connection.close()

if __name__ == '__main__':
    serve_forever()

通过以下命令行启动服务器:

$ python webserver3b.py

现在打开一个新的命令行终端然后运行下面的 curl 命令。你马上就能看到打印在屏幕上的 “Hello World!”

$ curl http://localhost:8888/hello
Hello, World!

趁热打铁再打开一个命令行终端,同样输入 curl 命令:

$ curl http://localhost:8888/hello

如果你在 60 秒内完事,那这个命令行会挂在那里不会产生任何输出。运行在第一个终端中的服务器也没有打印新的请求主体,在原作者的 Mac 上看起来就是这样(在右下角黄色框内的窗口能看到第二条 curl 命令在挂着,等待服务器接受连接):
lsbaws_part3_it3

在等待足够长时间之后(超过 60 秒),你应该会看到第一次的 curl 打印出来的 * *

UPDATE: Sat, July 13, 2019

  • Updated the server code to run under Python 3.7+
  • Added resources used in preparation for the article

此系列的所有文章(已翻译):

发布了26 篇原创文章 · 获赞 22 · 访问量 2万+

猜你喜欢

转载自blog.csdn.net/Run_Bomb/article/details/96881972