zoukankan      html  css  js  c++  java
  • 一起写一个web服务器(1)

    转载自:http://python.jobbole.com/81524/
    有天一个女士出门散步,路过一个建筑工地,看到三个男人在干活。她问第一个男人,“你在干什么呢?”,第一个男人被问得很烦,咆哮道,“你没看到我在码砖吗?”。她对回答不满意,然后问第二个男人他在干什么。第二个男人回答,“我正在砌墙”,然后转移注意力到第一个男人,他说,“嘿,你码过头了,你要把最后一块砖拿掉。”。她还是对回答不满意,然后问第三个男人在干什么。第三个男人仰望着天空对她说,“我正在建造世界上最大的教堂。”。当他站在那里仰望天空的时候,另外两个男人开始争论砖位置不对的问题。第三个男人转向前两个男人说,“嘿,伙计们,别担心那块砖了,那是里面的墙,它会被灰泥堵塞起来,然后没人会看到那块砖。去另一层干活吧。“

    故事的寓意是说,当你了解整个系统,理解不同的部分如何组织到一起的(砖、墙、教堂),你就能找出问题并快速解决之(砖位置不对)。

    这跟从零开始搭建你的WEB服务器有什么关系呢?

    我相信,要成为优秀的开发者,你必须对你每天都用的底层的软件系统有进一步的理解,包括编程语言、编译器和解释器、数据库和操作系统、WEB服务器和WEB框架。为了更好更深入的理解这些系统,你可以从零开始一块砖地,一面墙地,重建它们。

    子曰:闻之我也野,视之我也饶,行之我也明

    “我看过的,我还记得。”

    “我做过的,我都理解了。”

     

    (子曰:闻之我也野,视之我也饶,行之我也明)

    此时我希望你能够相信,从重建不同的软件系统来开始来学习它们是如何工作的,是一个好主意。

    在这个由3部分组成的系列文章中,我会向你展示怎样搭建一个基本的WEB服务器。咱们开始吧。

    重中之重,什么是WEB服务器?

    简而言之,它是一个位于一个物理服务器上的网络服务器(呀,服务器上的服务器),它等待客户端发送请求。当它接收到一个请求,就会生成一个响应并回发给客户端。客户端和服务器使用HTTP协议通信。客户端可以是浏览器或者别的使用HTTP协议的软件。

    一个非常简单的WEB服务器实现长什么样呢?以下是我写的一个。例子是用Python语言写的,但是即使你不会Python(它是一个非常易学的语言,试试!),你仍然可以通过代码和下面的解释理解相关概念:

    Python
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    21
    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 ...' % PORT
    while 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()

    把上面的代码保存到webserver1.py或者直接从GitHub下载,然后像下面这样在命令行运行它

    Python
    1
    2
    $ python webserver1.py
    Serving HTTP on port 8888

    现在在你的WEB浏览器地址栏里输入以下URL http://localhost:8888/hello,敲回车,见证奇迹的时刻。你会看到浏览器显示”Hello, World!“,像这样:

    认真做一下吧,我会等你的。

    做完了?很好。现在我们讨论一下它到底怎么工作的。

    首先我们从你刚才键入的WEB地址开始。它叫URL,这是它的基本结构:

    这个就表示怎样告诉浏览器要查找和连接的WEB服务器地址,和你要获取的服务器上的页面(路径)。但是在浏览器发送HTTP请求前,浏览器需要先和WEB服务器建立TCP连接。然后浏览器在TCP连接上发送HTTP请求,然后等待服务器回发HTTP响应。当浏览器接收到响应后,显示响应,在本次例子中,浏览器显示“Hello, World!”。

    我们再详细探索一下客户端和服务器在发送HTTP请求和响应前如何建立TCP连接的。在建立连接,它们必须使用所谓的sockets。用你命令行下的telnet手动模拟浏览器吧,而不是直接使用浏览器。

    在运行WEB服务器的同一台电脑上,在命令行启动一个telnet会话,指定连接到localhost主机,连接端口为8888,然后按回车:

    Python
    1
    2
    3
    $ telnet localhost 8888
    Trying 127.0.0.1
    Connected to localhost.

    此时,你已经和运行在你本地主机的服务器建立了TCP连接,已经准备好发送并接收HTTP消息了。下图中你可以看到一个服务器要经过的标准步骤,然后才能接受新的TCP连接。

    在同一个telnet会话中,输入 GET /hello HTTP/1.1然后敲回车:

    Python
    1
    2
    3
    4
    5
    6
    7
    $ telnet localhost 8888
    Trying 127.0.0.1
    Connected to localhost.
    GET /hello HTTP/1.1
     
    HTTP/1.1 200 OK
    Hello, World!

    你完成了手动模拟浏览器!你发送了一个HTTP请求并得到了一个HTTP响应。这是HTTP请求的基本结构:

    HTTP请求由行组成。行指示了HTTP方法(GET,因为我们请求我们的服务器返回给我们一些东西)、代表我们想要的服务器上的“页面”的路径 /hello和协议版本。

    为了简单起见,此时我们的WEB服务器完全忽略了上面的请求行。你也可以输入任何垃圾字符取代“GET /hello HTTP/1.1”,你仍然会得到“Hello, World!”响应。

    一旦你输入了请求行,敲了回车,客户端就发送请求给服务器,服务器读取请求行,打印出来然后返回相应的HTTP响应。

    以下是服务器回发给客户端(这个例子中是telnet)的HTTP响应:

    咱们分析一下它,响应包含了状态行HTTP/1.1 200 OK,随后一个必须的空行,和HTTP响应body。

    响应状态行TTP/1.1 200 OK包含了HTTP版本,HTTP状态码和HTTP状态码理由短语OK。浏览器得到响应时,它就显示响应的body,所以你就看到了“Hello, World!”

    这就是WEB浏览器怎么工作的基本模型。总结来说:WEB服务器创建一个监听socket然后开始循环接受新连接。客户端初始化一个TCP连接,在连接成功后,客户端发送HTTP请求到服务器,服务器响应一个显示给用户的HTTP响应。客户端和服务器都使用socket建立TCP连接。

    你现在你拥有了一个非常基础的WEB服务器,你可以用浏览器或其他的HTTP客户端测试它。正如你看到的,使用telnet手动输入HTTP请求,你也就成了一个人肉 HTTP 客户端。

    对你来说有一个问题:“怎样在你的刚完成的WEB服务器下运行 Django 应用、Flask 应用和 Pyramid  应用?在不单独修改服务器来适应这些不同的 WEB 框架的情况下。”

    我会在本系列的第 2 部分秀给你看的。请保持关注哦。

    顺便说下,我在写一本书《一起构建WEB服务器:第一步》,它解释了从零开始写一个基本的WEB服务器,还更详细地讲解了我上面提到的话题。订阅邮件组来获取关于书籍和发布时间和最近更新。

  • 相关阅读:
    box-shadow使用指南
    chrome的input默认样式黄色背景以及选中加粗的边框处理
    Spring AOP执行方法
    Spring JDBC主从数据库访问配置
    JS 命名冲突
    Data truncation: Truncated incorrect DOUBLE value 解决方案
    MySQL DATE_ADD() 函数
    Codeforces Round #340 (Div. 2)
    2020牛客寒假算法基础集训营3
    Codeforces Round #377 (Div. 2)
  • 原文地址:https://www.cnblogs.com/songlin123/p/10908287.html
Copyright © 2011-2022 走看看