【问题标题】:Web page only displaying after server stopped网页只在服务器停止后显示
【发布时间】:2016-10-26 06:08:18
【问题描述】:

出于学习目的,我正在用 Erlang 编写一个自制的 Web 服务器。当前的实现可以解析 HTTP GET 请求并做出相应的响应。问题是在我关闭服务器进程之前,我的测试 HTML 文件不会显示在 Web 浏览器中。我在控制台中看到打印件发送的消息,但 Web 浏览器一直在加载,直到服务器停止。在服务器停止的同一时刻显示页面。这是为什么呢?

listener(Listen) ->
  case gen_tcp:accept(Listen) of
    {ok, Client} ->
      case gen_tcp:recv(Client, 0) of
        {ok, Request} ->
          workers:worker({Client, Request});
        {error, closed} ->
          io:format("Socket closed.~n");
        {error, _Reason} ->
          io:format("Error: ~w~n", [_Reason])
      end,
      listener(Listen);
    {error, Error} ->
      io:format("Error ~w~n", [Error]),
      error
  end.

worker({Client, Request}) ->
  {Request_line, Headers, Body} = http_parse:parse_request(Request),
  Response = http_parse:create_response({Request_line, Headers, Body}),
  case gen_tcp:send(Client, Response) of
     ok ->
      io:format("Message sent!~n");
    {error, Reason} ->
      io:format("Could not send packet: ~w~n", [Reason])
  end.

上面是我写的一些代码。我已经忽略了解析,但这部分有效。 listener/1 接收通过使用选项列表 {active, false} 调用 gen_tcp:listen/2 创建的套接字。任何关于为什么页面仅在服务器关闭后才显示的指导表示赞赏。

【问题讨论】:

  • 只是一个想法,但是您的服务器必须阻塞在您期望继续执行的某个地方,并且在您停止服务器之前不会完成该堆栈的执行。
  • 可能是这样,我只是不知道从哪里开始寻找。一切似乎都运行良好,我收到“消息已发送!”打印出。之后消息会卡在套接字中吗?
  • 另外一个想法,服务器发出的响应当前不使用任何标头。只有请求行,然后是正文。这会导致页面不显示吗?
  • 可能,但如果是这种情况,我不会期望您描述的行为。老实说,除了建议您调试服务器并查看它是否位于阻止进一步执行的东西之外,我对 erlang 的了解还不够多。
  • 网络上实际的 HTTP 响应数据是什么样的?也许响应不完整/格式错误,Web 浏览器不知道响应何时真正完成,所以它别无选择,只能关闭套接字。

标签: sockets erlang webserver


【解决方案1】:

问题是响应标头缺少Content-Length 数据。

如果没有Content-Length 数据,客户端假定断开连接将标志着数据(正文)段的结束。

您的服务器永远不会关闭连接(也不会实现超时),因此客户端一直在等待更多数据(它假设更多数据正在传输中)。

一旦连接关闭,客户端会将其标记为正文(数据)段的结尾。

您应该考虑实施超时以及管理Content-LengthConnectionKeep-Alive 的响应标头。

考虑阅读一些specs 或在维基百科中阅读有关HTTP Protocolheaders 的更多信息。

【讨论】:

    猜你喜欢
    • 2019-02-07
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2012-10-05
    • 1970-01-01
    • 2019-03-10
    • 2017-04-02
    • 2019-05-28
    相关资源
    最近更新 更多